Почему я не могу передать std::make_unique в качестве параметра функции?

#c #c 11 #templates #unique-ptr

Вопрос:

Может ли кто-нибудь объяснить мне, почему я могу звонить std::make_unique<S> только с одним параметром шаблона , т. Е. S Вот так:

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

Но я не могу перейти std::make_unique<S> к функции, которая сделает это за меня, вот так:

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

Ошибка, показанная компилятором, является:

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

Я работаю с Visual Studio 2017 в Windows 10.

Комментарии:

1. Решением было бы пройти [](auto amp;amp;... args) { return std::make_unique<S>(decltype(args)(args)...); } .

2. Кроме того, это: Args... args не позволяет пересылать.

3. @StoryTeller-UnslanderMonica Возможно, было бы неплохо также указать, что Argsamp;amp; ...args позволит перенаправлять

4. @Const Это простой код, чтобы показать пример. В реальном коде я должен повторно использовать существующий метод, например call_method .

Ответ №1:

Подпись для std::make_unique является

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

Если вы вызываете make_unique напрямую, компилятор использует дедукцию аргументов шаблона, чтобы вывести, что Args должно быть, из того, с чем вы его вызываете. Передавая std::make_unique<S> свою функцию, вы указываете, что Args это пустой пакет параметров, и поэтому std::make_unique ожидаете нулевых параметров и пытаетесь по умолчанию построить S. Это то же самое, что звонить std::make_unique<S>(); напрямую.