Naruk
Naruk

Reputation: 1

C++ Recursive Variadic Templates with extendes Base case

i want to use recursive variadic templates with a base case with more than 2 types. The following example does not compile. What could be the problem?

My expectation was that f<int, int>(5) would call a case like:

[with T = int; Arg = int; Args = {int}]

but that seems to be no option for the compiler (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

Upvotes: 0

Views: 56

Answers (1)

Ted Lyngmo
Ted Lyngmo

Reputation: 117433

You can combine both cases and use a constexpr if statement in the function template:

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

Output:

0
---
3
2
1
0

Upvotes: 1

Related Questions