use*_*336 7 c++ templates constexpr
尝试在特定类类型上为该类的特定构造函数设置make_shared别名.我最好的尝试:
class foo { public: foo(int x) : y(x) {} int y; };
constexpr auto newfoo = static_cast<std::shared_ptr<foo>(*)(int)>(std::make_shared<foo>);
Run Code Online (Sandbox Code Playgroud)
产量:
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>);
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
std::make_shared是一个可变参数函数模板。您仅指定<foo>为模板参数,但您还需要int其中的某个位置。无论如何,您的方法注定会失败,因为make_shared它依赖于模板参数的布局方式,并且在 C++ 中使用重载集通常很麻烦。
我的建议是创建一个包装函数:
constexpr auto newfoo(int x)
{
return std::make_shared<foo>(x);
}
Run Code Online (Sandbox Code Playgroud)
在我看来,它更容易编写、阅读和理解。如果您确实需要 SFINAE 友好性并且noexcept,您可以重复正文三遍:
constexpr auto newfoo(int x)
-> decltype(std::make_shared<foo>(x))
noexcept(noexcept(std::make_shared<foo>(x)))
{ return std::make_shared<foo>(x); }
Run Code Online (Sandbox Code Playgroud)
可以使用宏来使上述声明不那么痛苦。
如果你真的想要一个函数指针,这似乎可行:
auto newfoo =
static_cast<std::shared_ptr<foo>(*)(const int&)>(
&std::make_shared<foo, const int&>);
Run Code Online (Sandbox Code Playgroud)
看一下make_shared的声明:
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
Run Code Online (Sandbox Code Playgroud)
你需要供应T=foo一些东西Args...。由于Args...是转发引用包,因此它总是会推导出左值引用或右值引用。这就是为什么<foo, const int&>是一组有效的模板参数而<foo, int>不是。
正如泽菲克在评论中指出的那样,所有这些都可以简化为:
constexpr auto newfoo = &std::make_shared<foo, const int&>;
Run Code Online (Sandbox Code Playgroud)
这里并不真正需要演员阵容。