Why I cannot pass std::make_unique<S> as a function parameter?

Viewed 252

Can anyone make it clear for me why I can call std::make_unique<S> with only one template parameter, i.e. S, like this:

auto p = std::make_unique<S>(12, 13);

But, I cannot pass std::make_unique<S> to a function to do that for me, like this:

template <typename FuncType, typename ...Args >
void call_method(FuncType f, Args... args)
{
   f(std::forward<Args>(args)...);
}

struct S
{
   S(int x, int y) {}
};

int main()
{
   call_method(std::make_unique<S>, 12, 13); // not working
   // call_method(std::make_unique<S, int , int>, 12, 13); // works fine
   return 0;
}

The shown error by the compiler is:

Error C2512 'S::S': no appropriate default constructor available.

I am working with Visual Studio 2017 on Windows 10.

1 Answers

The signature for std::make_unique is

template<class T, class... Args>
unique_ptr<T> make_unique(Args&& ...args);

If you call make_unique directly the compiler is using template argument deduction to deduce what Args should be from what you are invoking it with. By passing std::make_unique<S> to your function, you are stating that Args is an empty parameter pack, and therefore std::make_unique is expecting zero parameters and tries to default construct an S. It is the same as calling std::make_unique<S>(); directly.

Related