别名模板、偏特化和无效参数类型 void

Alias template, partial specialization and the invalid parameter type void

考虑以下代码:

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 的行,它没有编译,而是我得到错误:

In substitution of 'template using Alias = S [with Args = {void}]'

[...]

error: invalid parameter type 'void'

问题很简单:我在这里错过了什么?

来自 [dcl.fct],强调我的:

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.

在这种情况下,Args... 是依赖类型包,因此那里不允许 void。 [temp.deduct]:

中的注释中重复了这个想法

[ Note: Type deduction may fail for the following reasons:
— [...]
— Attempting to create a function type in which a parameter has a type of void, or in which the return type is a function type or array type.
— [...]
—end note ]

请注意,S<void(void)> 可以编译,因为 void(void) 是非依赖的并且等同于 void(),因此 Ret(Args...) 永远不会被推断为具有 void参数列表 - 它是用 Args... 为空推导出来的。


至少有一个简单的解决方法,您可以只写 Alias<>.