2

I'm trying using pack parameter template to fit some cases. I want to stop the template packed parameter expanding when there is only one parameter in the list. I want to use the typename explicitly when instancing the template, rather than using the typename to declare variables.

Here is a minimal example:

template <class T>
void f() {}

template <class T, class... Args>
void f() {
  f<Args...>();
}

int main() {
  f<int, int, double>();
  return 0;
}

When compiling the code, I got the error:

demo.cc: In instantiation of ‘void f() [with T = int; Args = {double}]’:
demo.cc:6:13:   required from ‘void f() [with T = int; Args = {int, double}]’
demo.cc:10:23:   required from here
demo.cc:6:13: error: call of overloaded ‘f<double>()’ is ambiguous
    6 |   f<Args...>();
      |   ~~~~~~~~~~^~
demo.cc:2:6: note: candidate: ‘void f() [with T = double]’
    2 | void f() {}
      |      ^
demo.cc:5:6: note: candidate: ‘void f() [with T = double; Args = {}]’
    5 | void f() {
      |      ^

I have read the following information from cppreferrence here:

A pattern followed by an ellipsis, in which the name of at least one parameter pack appears at least once, is expanded into zero or more comma-separated instantiations of the pattern, where the name of the parameter pack is replaced by each of the elements from the pack, in order.

It may be why the compiler can't decide whether to use void f() [with T = double] or void f() [with T = double; Args = {}]

Can I stop the unpacking only by using template parameters rather than using input argument of function?

Jason Pan
  • 702
  • 7
  • 21
  • Dupe:[Ambiguous call when recursively calling variadic template function overload](https://stackoverflow.com/questions/42063084/ambiguous-call-when-recursively-calling-variadic-template-function-overload) – Jason Jun 28 '22 at 16:38
  • @AnoopRana Thanks for your info. The linked question is asking why it's ambiguous, which in my question I have declared. This question is asking for how to solve the ambiguity. – Jason Pan Jun 29 '22 at 01:15
  • I agree but solving this is trivial(at least to me). – Jason Jun 29 '22 at 03:41

1 Answers1

2

You can constrain the variadic version of the function with SFINAE to stop it from being called if the parameter pack is empty. That would look like

template <class T, class... Args, std::enable_if_t<(sizeof...(Args) > 0), bool> = true>
void f() {
  f<Args...>();
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402