Constexpr重载模板函数的别名

时间:2017-09-14 14:50:31

标签: 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>);

收率:

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>);

我做错了什么?

1 个答案:

答案 0 :(得分:4)

std::make_shared可变参数函数模板。您只是将<foo>指定为模板参数,但在那里您还需要int。无论如何,您的方法必然会失败,因为它依赖于make_shared模板参数的布局方式,并且因为在C ++中使用重载集通常很麻烦。 / p>

我建议改为创建一个包装函数:

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&>;

这里不需要演员。