Reputation: 655
Trying to alias make_shared on a specific class type for a specific 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>);
Yields:
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?
Upvotes: 8
Views: 619
Reputation: 93324
std::make_shared
is a variadic function template. You are only specifying <foo>
as a template parameter, but you would also need an int
somewhere in there. Regardless, your approach is bound to fail as it's reliant on how make_shared
's template arguments were laid out and because it's generally cumbersome to work with overload sets in C++.
What I suggest is to create a wrapper function instead:
constexpr auto newfoo(int x)
{
return std::make_shared<foo>(x);
}
In my opinion it is 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 want a function pointer, this seems to work:
auto newfoo =
static_cast<std::shared_ptr<foo>(*)(const int&)>(
&std::make_shared<foo, const int&>);
Look at make_shared
's declaration:
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
You need to supply T=foo
and something for Args...
. Since Args...
is a forwarding reference pack, it will always either deduce to lvalue references or rvalue references. This is why <foo, const int&>
is a valid set of template parameters and <foo, int>
is not.
As Zefick pointed out in the comments, all of this can be simplified to:
constexpr auto newfoo = &std::make_shared<foo, const int&>;
The cast is not really needed here.
Upvotes: 4