I'm trying to use variadic template to refactor some of my code, but the compiler has "no matching function for call" error. Below is a simplified version (it may not make sense for functionality, but an example to reproduce the error):
// base case
void testFunc(int i) { std::cout << i << std::endl; }
template <class T, class... Args> void testFunc(int i) {
  T t = 0;
  std::cout << t << std::endl;
  testFunc<Args...>(i);
}
int main() {
  testFunc<int, long, float>(1);
  return 0;
}
The error messages:
main.cpp:9:3: error: no matching function for call to 'testFunc'
  testFunc<Args...>(i);
  ^~~~~~~~~~~~~~~~~
main.cpp:9:3: note: in instantiation of function template specialization 'testFunc<float>' requested here
main.cpp:9:3: note: in instantiation of function template specialization 'testFunc<long, float>' requested here
main.cpp:13:3: note: in instantiation of function template specialization 'testFunc<int, long, float>' requested here
  testFunc<int, long, float>(1);
  ^
main.cpp:6:40: note: candidate template ignored: couldn't infer template argument 'T'
template <class T, class... Args> void testFunc(int i) {
                                       ^
1 error generated.
It looks like that the unwrapping of template parameters is working, and stops at the base case. But I have defined the base case. Why there is no matching function?
The problem is that calling
testFunc<Args...>(i);
you call the template version of testFunc(), not the base case version.
And when Args... is empty, there isn't a template version available.
To solve this problem... if you can use C++17, you can use if constexpr, as suggested by YSC.
For C++11 and C++14, I propose to use the template partial specialization of a struct.
The following is a full working example
#include <iostream>
// base case  
template <typename...>
struct foo
 { static void bar (int i) { std::cout << i << std::endl; } };
// recursive case
template <typename T, typename ... Args>
struct foo<T, Args...>
 {
   static void bar (int i)
    {
      std::cout << T{} << std::endl;
      foo<Args...>::bar(i);
    }
 };
int main()
 {
   foo<int, long, float>::bar(1);
 }
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With