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

4
在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()却不能吗?


请注意,在 Visual C++ 2008 中,shared_ptr 位于 std::tr1 中,并且未实现 make_sharedmake_shared 不是 TR1 的一部分)。 - James McNellis
听起来你在使用 ::make_shared - Johannes Schaub - litb
忽略2008位,我把IDE和编译器搞混了。 - Mark Bryant
我可以在VS2010中重现这个问题。我将其切换为使用boost::shared_ptr,但在VS2008中无法编译。它抱怨“无法推断出'T'的模板参数”,这对我来说毫无意义,因为你明确指定了T(int)。 - James McNellis
2个回答

6

看起来这是编译器的一个bug。以下是重现问题所需的最小代码:

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<T> ns :: func(void)':无法推断'T'的模板参数”

Comeau对此代码没有问题。


1
我在Microsoft Connect上提交了一个缺陷报告:https://connect.microsoft.com/VisualStudio/feedback/details/557653 - James McNellis

0

我在自己的代码中遇到了似乎是同样的问题。我将其简化为以下最小代码:

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的情况下使用这种技术,尽管我还没有尝试过。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接