Variadi c шаблон не компилируется - PullRequest
1 голос
/ 09 июля 2020
#include <iostream>

template<typename A, typename... B>
void prints(A num, B... args){
    std::cout << num << std::endl;
    prints(args...);
}

int main(){
    prints(1,2,3);
    return 0;
}

При компиляции я получаю следующие ошибки:

In instantiation of 'void prints(A, B ...) [with A = int; B = {}]':
error: no matching function for call to 'prints()'

main.cpp:4:10: note:   template argument deduction/substitution failed:
main.cpp:7:11: note:   candidate expects at least 1 argument, 0 provided

Ответы [ 2 ]

5 голосов
/ 09 июля 2020

Ваша функция ожидает 1 или более параметров:

template<typename A, typename... B>
void prints(A num, B... args)

Когда вы вызываете ее только с 1 параметром, пакет args... пуст, поэтому рекурсивный вызов:

prints(args...);

становится

prints();

Но ваша функция ожидает (по крайней мере) 1 аргумента, поэтому не может соответствовать этому вызову.

Вам нужно добавить перегрузку с нулевым аргументом prints() для соответствия пустому вызову:

void prints()
{ }

, и вы должны объявить его перед рекурсивной версией.

Как указано Evg (спасибо), начиная с C ++ 17, вы можете избежать перегрузка с нулевым аргументом и, используя if constexpr, вы можете вызвать рекурсию только тогда, когда args... не пусто.

То есть ... начиная с C ++ 17 вы можете написать

template <typename A, typename... B>
void prints (A num, B... args) {
   std::cout << num << std::endl;

   if constexpr ( sizeof...(args) > 0u )
      prints(args...);
}

, и вам больше не нужна перегрузка с нулевым аргументом.

Обратите внимание, что если вы просто напишите (с простым if, no if constexpr)

   if ( sizeof...(args) > 0u )
      prints(args...);

вы получите (без перегрузки с нулевым аргументом) ошибку компиляции, потому что компилятор должен скомпилировать часть prints(args...) также, когда sizeof...(args) равно нулю (это ' s ровно if constexpr, чтобы этого избежать).

0 голосов
/ 10 июля 2020

Другое решение, использующее выражения свертки, показано ниже:

#include <iostream>
#include <utility>

template <class... TArgs>
void prints(TArgs&&... args) {
    (std::cout << ... << std::forward<TArgs>(args));
}

int main(){
    prints(1,2,3);
    return 0;
}
...