2017-09-14 134 views
7

尝试针对该类的特定构造函数的特定类类型尝试别名make_shared。我最好的尝试:Constexpr重载模板函数的别名

class foo { public: foo(int x) : y(x) {} int y; }; 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

产量:

error: invalid static_cast from type ‘<unresolved overloaded function type>’ to type ‘std::shared_ptr<foo> (*)(int)’ 
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>); 

我在做什么错?

回答

4

std::make_shared可变参数函数模板。您只指定<foo>作为模板参数,但您还需要在其中的某个地方使用int。无论如何,你的方法肯定会失败,因为它依赖于如何布置make_shared的模板参数,并且因为在C++中使用重载集合通常很麻烦。

我建议什么是创建一个包装函数:

constexpr auto newfoo(int x) 
{ 
    return std::make_shared<foo>(x); 
} 

在我看来,这是比较容易写,阅读和理解。如果你真的需要 SFINAE友好和noexcept,你可以repeat the body three times

constexpr auto newfoo(int x) 
    ->   decltype(std::make_shared<foo>(x)) 
     noexcept(noexcept(std::make_shared<foo>(x))) 
     {   return std::make_shared<foo>(x); } 

宏可以用来作出上述声明的痛苦。


如果你真的想要一个函数指针,这似乎工作:

auto newfoo = 
    static_cast<std::shared_ptr<foo>(*)(const int&)>(
     &std::make_shared<foo, const int&>); 

make_shared的声明:

template< class T, class... Args > 
shared_ptr<T> make_shared(Args&&... args); 

您需要提供T=foo和东西Args... 。由于Args...是转发参考包,它总是会推断为左值引用右值引用。这就是为什么<foo, const int&>是一组有效的模板参数,而<foo, int>则不是。

由于Zefick在评论中指出,所有这一切都可以简化为:

constexpr auto newfoo = &std::make_shared<foo, const int&>; 

是不是真的在这里所需要的演员。

+1

+1,但是你应该在你的“如果你真的想要”例子中使用'const int&'而不是'int &&'。就像,'const int i = 42; auto f = newfoo(i);'不起作用。 –

+0

@MilesBudnek:好点,改变我的回答 –

+2

'constexpr auto newfoo = std :: make_shared '只是工作。为什么我们需要演员? – Zefick