std::make_shared 作为默认参数无法编译

发布于 2024-09-01 09:42:33 字数 513 浏览 12 评论 0原文

在 Visual C++(2008 和 2010)中,以下代码无法编译,并出现以下错误:

#include <memory>

void Foo( std::shared_ptr< int >    test = ::std::make_shared< int >( 5 ) )
{
}

class P
{
    void
    Foo( std::shared_ptr< int > test = ::std::make_shared< int >( 5 ) )
    {
    }
};

错误 C2039: 'make_shared' : 不是 '`全局命名空间'' 的成员

错误 C3861: 'make_shared': 找不到标识符

它是抱怨 P::Foo() 而不是 ::Foo() 的定义。

有谁知道为什么 Foo() 有一个 std::make_shared 的默认参数是有效的,但 P::Foo() 却不是?

In Visual C++ (2008 and 2010), the following code does not compile with the following error:

#include <memory>

void Foo( std::shared_ptr< int >    test = ::std::make_shared< int >( 5 ) )
{
}

class P
{
    void
    Foo( std::shared_ptr< int > test = ::std::make_shared< int >( 5 ) )
    {
    }
};

error C2039: 'make_shared' : is not a member of '`global namespace''

error C3861: 'make_shared': identifier not found

It is complaining about the definition of P::Foo() not ::Foo().

Does anybody know why it is valid for Foo() to have a default argument with std::make_shared but not P::Foo()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

◇流星雨 2024-09-08 09:42:33

它看起来像是编译器中的错误。以下是重现该问题所需的最少代码:

namespace ns
{
    template <typename T>
    class test
    {
    };

    template <typename T>
    test<T> func()
    {
        return test<T>();
    }
}

// Works:
void f(ns::test<int> = ns::func<int>()) { }

class test2
{
    // Doesn't work:
    void g(ns::test<int> = ns::func<int>()) 
    { 
    }
};

Visual C++ 2008 和 2010 均报告:

错误 C2783: 'ns::test; ns::func(void)':无法推断出“T”的模板参数

Comeau 对此代码没有任何问题。

It looks like a bug in the compiler. Here is the minimal code required to reproduce the problem:

namespace ns
{
    template <typename T>
    class test
    {
    };

    template <typename T>
    test<T> func()
    {
        return test<T>();
    }
}

// Works:
void f(ns::test<int> = ns::func<int>()) { }

class test2
{
    // Doesn't work:
    void g(ns::test<int> = ns::func<int>()) 
    { 
    }
};

Visual C++ 2008 and 2010 both report:

error C2783: 'ns::test<T> ns::func(void)' : could not deduce template argument for 'T'

Comeau has no issues with this code.

变身佩奇 2024-09-08 09:42:33

我在自己的代码中遇到了似乎相同的问题。我将其归结为以下的最少代码:

namespace N
{
    template<typename T>
    T defaultValue()
    {
        return T();
    }

    template<typename T>
    void fun( const T& value = N::defaultValue<T>() ){}
}

int main(int argc, char* argv[])
{
    N::fun<int>();
    return 0;
}

这与 James McNellis 的示例略有不同 - 而且我认为,它强调了这样一个事实:默认参数初始化程序中的名称空间限定出了问题。

在这种情况下,defaultValue 和 fun 位于同一命名空间中,因此您可以轻松地从 N::defaultValue 中删除 N:: ,并且它可以工作。

如果 defaultValue 位于不同的命名空间中,您仍然可以通过使用 using 将其带入本地命名空间或编写本地转发模板函数来解决它,例如:

namespace N1
{
    template<typename T>
    T defaultValue()
    {
        return T();
    }
}
namespace N2
{
    template<typename T>
    T defaultValueFwd()
    {
        return N1::defaultValue<T>();
    }

    template<typename T>
    void fun( const T& value = defaultValueFwd<T>() ){}
}

int main(int argc, char* argv[])
{
    N2::fun<int>();
    return 0;
}

有点痛苦,但可行。我相信您可以在 make_shared 情况下使用此技术,尽管我还没有尝试过。

I hit what appears to be the same issue in my own code. The minimal code I boiled it down to was this:

namespace N
{
    template<typename T>
    T defaultValue()
    {
        return T();
    }

    template<typename T>
    void fun( const T& value = N::defaultValue<T>() ){}
}

int main(int argc, char* argv[])
{
    N::fun<int>();
    return 0;
}

This is slightly different to James McNellis example - and, I think, highlights the fact that it is the namespace qualification in the default argument initiliser where it goes wrong.

In this case defaultValue and fun are in the same namespace, so you can trivially remove N:: from N::defaultValue and it works.

If defaultValue is in a different namespace you can still workaround it by either bringing it into the local namespace with using, or writing a local forwarding template function, e.g.:

namespace N1
{
    template<typename T>
    T defaultValue()
    {
        return T();
    }
}
namespace N2
{
    template<typename T>
    T defaultValueFwd()
    {
        return N1::defaultValue<T>();
    }

    template<typename T>
    void fun( const T& value = defaultValueFwd<T>() ){}
}

int main(int argc, char* argv[])
{
    N2::fun<int>();
    return 0;
}

A bit of a pain, but workable. I believe you could use this technique in the make_shared case, although I haven't tried it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文