4

For C legacy reasons, the following definitions in C++ are equivalent:

void foo() {}
void foo(void) {}

What happens when foo is in a templated class ? For example:

template <typename T> struct C { void foo(T) {} };

int main()
{ C<void> c;
  c.foo();
}

MSVC (19.30) accepts this code, but gcc (11.2) rejects it. It seems that compilers disagree as to whether foo(T) is equivalent to foo() when T = void.

Which is correct ?

Evg
  • 25,259
  • 5
  • 41
  • 83
user1958486
  • 571
  • 3
  • 8
  • I think the `void` as a template argument is invalid. Possible duplicate: [Using 'void' template arguments in C++](https://stackoverflow.com/q/13372173/10871073) - but things *may* have changed in Standards released since that question/answer was posted (over 9 years ago). The C++11 Standard is quoted in [this answer](https://stackoverflow.com/a/13372928/10871073) – Adrian Mole Jan 03 '22 at 09:06
  • Also maybe relevant: [How can an incomplete type be used as a template parameter to vector here?](https://stackoverflow.com/q/31345193/10871073) And, from the Standard: *A type cv void is an incomplete type that cannot be completed;* – Adrian Mole Jan 03 '22 at 09:12
  • 1
    `void` is definitely allowed as a class template argument, and there is plenty of code that uses that. A non-template function declaration with a (single) `void` parameter type is also allowed, but is synonymous with an empty parameter list. The issue is whether the `void` is allowed as a function parameter type when `void` is not present literally as a keyword, but is the value of a template argument. – user1958486 Jan 03 '22 at 09:21
  • OK. I was imprecise. I meant `void` is not allowed as a templated argument type (I think). – Adrian Mole Jan 03 '22 at 09:34
  • The excerpt from the C++11 Standard in the *answer* I linked in my first comment (by James McNellis) seems to cover your case completely. Your `void` argument is **not** non-dependent. I really can't see how that answer does not answer this question, so I'm closing this as a duplicate. – Adrian Mole Jan 03 '22 at 09:41

1 Answers1

3

The specification says (C++11 §8.3.5[dcl.func]/4):

A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list. Except for this special case, a parameter shall not have type cv void.

And since in your case you have a dependent type(depending on T), gcc is correct.

Jason
  • 36,170
  • 5
  • 26
  • 60