别名模板、偏特化和无效参数类型 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<>
.
考虑以下代码:
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 cvvoid
.
在这种情况下,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 ofvoid
, 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<>
.