Constexpr alias overloaded template function

Trying to alias make_shared for a particular class type for a particular constructor of that class. My best attempt:

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

Productivity:

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

What am I doing wrong?

+7
c ++ templates constexpr
source share
1 answer

std::make_shared is a variation function template. You specify <foo> as a template parameter, but you will also need an int somewhere there. Regardless, your approach will inevitably fail, because it depends on how the arguments to the make_shared template make_shared , and because it generally cumbersomely works with overload sets in C ++.

I suggest creating a wrapper function instead:

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

In my opinion, it’s easier to write, read and understand. If you really need SFINAE friendliness and noexcept , you can 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); } 

A macro can be used to make the above declaration less painful.


If you really need a function pointer, this works:

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

Look at the make_shared :

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

You need to put T=foo and something for Args... Since Args... is a forwarding reference package, it will always either output references to lvalue or rvalue links. This is why <foo, const int&> is a valid set of template parameters, and <foo, int> is not.

As noted in Zefick's comments, all of this can be simplified:

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

Actually, the actor is not needed.

+4
source share

All Articles