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.