请考虑以下代码:
template<typename F>
struct S;
template<typename Ret, typename... Args>
struct S<Ret(Args...)> { };
template<typename... Args>
using Alias = S<void(Args...)>;
int main() {
S<void(int)> s;
Alias<int> alias;
}
它正常工作,正如预期的那样,涉及S
的行和涉及Alias
的行都定义了相同的类型S<void(int)>
。
现在,请考虑以下更改:
int main() {
S<void(void)> s; // this line compiles
Alias<void> alias; // this line does not
}
我希望它能够编译,原因与上面提到的相似
不言而喻,由于涉及Alias
的行,它没有编译,而是我得到了错误:
使用Alias = S代替&#39;模板[使用Args = {void}]&#39;
[...]
错误:参数类型无效&#39;无效&#39;
问题很简单:我错过了什么?
答案 0 :(得分:5)
来自[dcl.fct],强调我的:
由非依赖类型
void
的单个未命名参数组成的参数列表等同于空参数列表。除了这种特殊情况,参数不应具有 cvvoid
类型。
在这种情况下,Args...
是依赖类型包,因此不允许void
。这个想法在[temp.deduct]的注释中重复:
[注意:类型扣除可能因以下原因而失败:
- [...]
- 尝试创建一个函数类型,其中参数的类型为void
,或者返回 type是函数类型或数组类型 - [...]
-end note]
请注意S<void(void)>
编译,因为void(void)
不依赖,并且等同于void()
,因此永远不会推断Ret(Args...)
在参数中有void
列表 - 它是Args...
空的推断。
至少有一个简单的解决方法,你可以写Alias<>
。