我认为这段代码是有效的C ++。 MSVC同意,但gcc似乎不同意。 MSVC和我错了吗? (或者我应该输入略有不同的内容?)
#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();
}
错误消息:
<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
如果我将文字void
编写为参数类型,请使用 gcc似乎很好(请参见函数g()
的参数)。但是如果我写T
然后将T
解析为void
(请参见函数f()
的参数),那是不高兴的。
答案 0 :(得分:6)
否,您的示例不是有效的C ++。在Standard section [dcl.fct], paragraph 4中找到了允许(void)
成为不带参数的函数参数列表的规则:
由单个非依赖类型
void
的未命名参数组成的参数列表等效于空参数列表。除此特殊情况外,参数的类型不得为 cvvoid
。
您问题的关键是单词“ non-dependent”,即不依赖于模板参数。该要求可能是这样写的,因为在模板中编写函数声明void func(T);
,期望它始终是仅带有一个参数的函数类型,然后发现在某种情况下可能不是
所以:
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