#c #templates #c 17
#c #шаблоны #c 17
Вопрос:
я хочу использовать рекурсивные переменные шаблоны с базовым вариантом с более чем 2 типами. Следующий пример не компилируется. В чем может быть проблема?
Я ожидал, что f<int, int>(5) вызовет случай, подобный:
[с T = int; Arg = int; Args = {int}]
но, похоже, это не вариант для компилятора (g c 17) 😉
template<class T, typename Arg, typename... Args>
void f(T a) {
}
template<class T, typename Arg>
void f (T a) {
}
int main() {
f<int, int>(5);
return 0;
}
<source>: In function 'int main()':
<source>:11:18: error: call of overloaded 'f<int, int>(int)' is ambiguous
11 | f<int, int>(5);
| ^
<source>:2:6: note: candidate: 'void f(T) [with T = int; Arg = int; Args = {}]'
2 | void f(T a) {
| ^
<source>:6:6: note: candidate: 'void f(T) [with T = int; Arg = int]'
6 | void f (T a) {
| ^
Compiler returned: 1
Комментарии:
1. Почему вы ожидаете
[with T = int; Arg = int; Args = {int}]
именно этого? Вы указали 2int
параметра дляf
. Вы ожидаетеArgs
, что вас выведут из5
?2. Да, я думал, что это сработает. Потому что в этом примере это работает (да, я знаю, что немного по-другому, но я думал, что это будет аналог):
template<typename X> int square(X num) { return num * num; } int main() { return square(5); }
3. Разница в том, что вы не указываете аргументы шаблона, поэтому должен выполняться вычет.
Ответ №1:
Вы можете объединить оба случая и использовать оператор constexpr if в шаблоне функции:
#include <iostream>
template<class T, typename Arg, typename... Args>
void f(T a) {
std::cout << sizeof...(Args) << 'n';
if constexpr (sizeof...(Args) > 0) {
f<T, Args...>(a);
}
}
int main() {
f<int, int>(5);
std::cout << "---n";
f<int, int, double, float, int>(5);
}
Вывод:
0
---
3
2
1
0