Очень простой пример шаблона переменной:
Предположим, мы хотим иметь функцию, которая принимает переменное число аргументов и печатает их все.Например:
print("Hello", 1, 3.14, 5L);
Для того, чтобы эта функциональность работала, нам в основном потребовалось бы две функции:
Первая, функция, которая принимает переменное число аргументов:
template<typename T, typename... Args>
void print(T t, Args ...args){
std::cout << t << ", ";
print(args...);
}
Некоторое объяснение:
1.) Пакеты параметров, обозначенные многоточием (...), которые появляются в списке параметров.
typename...Args
| | << Optional whitespace. Can have multiple whitespaces in between them
Args...args
Это означает, что этивсе одинаковы.
typename ...args
typename...args
typename ... args
Так что вам не нужно беспокоиться о правильном расположении пропусков там.Тем не менее, в качестве наилучшей практики следует использовать IMO не более одного пробела.
2.) Расширение пакета: шаблон с последующим многоточием.
print(args...); //expand when you wish to use them
3.) Пакет параметров принимает ноль или более шаблонов args.Итак, print(T t, Args... args)
принимает один или несколько аргументов.
Как только вы поймете это, мы можем визуализировать поток вызовов, как показано ниже:
print("Hello", 1, 3.14, 5L);
переводитв:
print(string, int, float, long);
который звонит
print(int, float, long);
который звонит
print(float, long); // say Level 2
который звонит
print(long); // say Level 1
который звонит
print(); // say Level 0
Если вы тщательно следовали пункту 3, вы, должно быть, поняли, что print(T t, Args... args)
не может обработать вызов на уровне 0.
Поэтому нам нужна другая функция с таким же именем, чтобы наверстать упущенное на любом уровне.> = 0.
Второй, функция для захвата вызова на вершине стека вызовов :
Поймать на уровне0:
void print(){}
или, Поймать на уровне 1:
template<typename T>
void print(T t){ std::cout << t;}
или, Поймать на уровне 2:
template<typename T, typename U>
void print(T t, U u){ std::cout << t << ", " << u;}
и т. Д ...
Любой из них будет работать.Надеюсь, это поможет вам в следующий раз, когда вы приступите к написанию такой функции или класса.