I think this code is valid C++. MSVC agrees but gcc seems to disagree. Are MSVC and I wrong? (Or should I be typing something slightly different?)
#include <iostream>
#include <string>
#include <vector>
#include <functional>
template <typename T>
struct S
{
template <typename R>
void f(std::function<R(T)> fn)
{
auto p = &fn;
++p;
}
template <typename R>
void g(std::function<R(void)> fn)
{
auto p = &fn;
++p;
}
};
void f()
{
S<void> s;
auto p = &s;
++p;
}
int main()
{
f();
}
error message:
<source>: In instantiation of 'struct S<void>':
<source>:26:11: required from here
<source>:11:8: error: invalid parameter type 'void'
void f(std::function<R(T)> fn)
^
<source>:11:8: error: in declaration 'void S<T>::f(std::function<R(T)>)'
Compiler returned: 1
gcc seems to be fine if I write the literal, void
, as the parameter type (see parameter to function g()
). But it is unhappy if I write T
and then resolve T
to void
(see parameter to function f()
).
No, your example is not valid C++. The rule that allows (void)
to be a function parameter list with no parameters is found in Standard section [dcl.fct], paragraph 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 cvvoid
.
The key for your question is the word "non-dependent", meaning not depending on a template parameter. The requirement was probably written this way because it would be too surprising to write the function declaration void func(T);
within a template, expecting it to always be a function type taking exactly one parameter, and then find in one case it might not be.
So:
void f1(void); // okay - classic style from C
void f2(void nothing); // error - the phony "void" parameter cannot be named
void f3(const void); // error - const void is a different type
using VoidType = void;
void f4(VoidType); // okay - using a non-dependent type alias
template <typename T>
void f5(T);
void (*fptr)(void) = f5<void>; // error - dependent parameter type cannot be void
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