依赖非类型参数包:标准怎么说?
Dependent non-type parameter packs: what does the standard say?
我认为以下代码格式正确:
template< typename T >
using IsSigned = std::enable_if_t< std::is_signed_v< T > >;
template< typename T, IsSigned< T >... >
T myAbs( T val );
也有人说是病式的,因为C++17标准的§17.7(8.3):
Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if: (...) every valid specialization of a variadic template requires an empty template parameter pack, or (...)
在我看来 IsSigned< T >...
是一个从属模板参数,因此在模板定义时不能根据 §17.7 (8.3) 检查。例如,IsSigned< T >
对于 Ts 的一个子集可能是 void
,对于另一个子集或替换失败可能是 int
。对于 void
子集,空模板参数包确实是唯一有效的特化,但是 int
子集可以有许多有效的特化。这取决于实际的 T
参数。
这意味着编译器必须在模板实例化之后检查它,因为之前不知道T。那时完整的参数列表是已知的,可变参数为零。该标准规定如下(§17.6.3 (7)):
When N is zero, the instantiation of the expansion produces an empty list. Such an instantiation does not alter the syntactic interpretation of the enclosing construct
这就是我认为它格式正确的原因。
- 你怎么看?
- 我怎样才能确定地找出这种歧义?很难决定,因为代码编译但没有任何意义:§17.7 (8.3) 是 NDR,编译器不必引发任何编译错误。
代码格式错误,不需要诊断。
如果std::is_signed_v<T>
,则std::enable_if_t<std::is_signed_v<T>>
表示类型void
。否则,std::enable_if_t<std::is_signed_v<T>>
不表示有效类型。因此,myAbs
的每个有效特化都需要一个空的模板参数包。
根据 [meta.rqmts]/4,如果 std::enable_if
是特化的,则程序具有未定义的行为。因此,无法更改上述行为。
In my opinion IsSigned< T >...
is a dependent template parameter,
therefore it can not be checked against §17.7 (8.3) in template
definition time. IsSigned< T >
could be for example void
for one
subset of T
s, int
for another subset or substitution failure. For
the void
subset it is true, that the empty template parameter pack
would be the only valid specialization, but the int
subset could
have many valid specializations. It depends on the actual T
argument.
编译器无法检查它,就像它无法为您求解任意方程一样。 NDR(不需要诊断)正是为这种情况而设计的——程序格式错误,如果编译器确实能够检测到,则需要进行诊断。 NDR 允许编译器不检查它。
When N is zero, the instantiation of the expansion produces an empty
list. Such an instantiation does not alter the syntactic
interpretation of the enclosing construct.
我们说的规则是语义规则,不是句法规则,因为句法规则是以[gram]为单位的。
那么 NDR 规则的基本原理是什么?一般来说,它们解决的问题在实施策略中是不可重现的。例如,它们可能会导致代码在某些实现策略中行为不当,但不会在其他方面造成任何问题(并且不容易)。
此外,请注意标准在程序方面使用 "ill-formed" 等术语。因此,谈论一个孤立代码片段的格式是否正确并不总是合理的。在这种情况下,std::enable_if
需要不特化,否则情况可能会变得更复杂。
我认为以下代码格式正确:
template< typename T >
using IsSigned = std::enable_if_t< std::is_signed_v< T > >;
template< typename T, IsSigned< T >... >
T myAbs( T val );
也有人说是病式的,因为C++17标准的§17.7(8.3):
Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if: (...) every valid specialization of a variadic template requires an empty template parameter pack, or (...)
在我看来 IsSigned< T >...
是一个从属模板参数,因此在模板定义时不能根据 §17.7 (8.3) 检查。例如,IsSigned< T >
对于 Ts 的一个子集可能是 void
,对于另一个子集或替换失败可能是 int
。对于 void
子集,空模板参数包确实是唯一有效的特化,但是 int
子集可以有许多有效的特化。这取决于实际的 T
参数。
这意味着编译器必须在模板实例化之后检查它,因为之前不知道T。那时完整的参数列表是已知的,可变参数为零。该标准规定如下(§17.6.3 (7)):
When N is zero, the instantiation of the expansion produces an empty list. Such an instantiation does not alter the syntactic interpretation of the enclosing construct
这就是我认为它格式正确的原因。
- 你怎么看?
- 我怎样才能确定地找出这种歧义?很难决定,因为代码编译但没有任何意义:§17.7 (8.3) 是 NDR,编译器不必引发任何编译错误。
代码格式错误,不需要诊断。
如果std::is_signed_v<T>
,则std::enable_if_t<std::is_signed_v<T>>
表示类型void
。否则,std::enable_if_t<std::is_signed_v<T>>
不表示有效类型。因此,myAbs
的每个有效特化都需要一个空的模板参数包。
根据 [meta.rqmts]/4,如果 std::enable_if
是特化的,则程序具有未定义的行为。因此,无法更改上述行为。
In my opinion
IsSigned< T >...
is a dependent template parameter, therefore it can not be checked against §17.7 (8.3) in template definition time.IsSigned< T >
could be for examplevoid
for one subset ofT
s,int
for another subset or substitution failure. For thevoid
subset it is true, that the empty template parameter pack would be the only valid specialization, but theint
subset could have many valid specializations. It depends on the actualT
argument.
编译器无法检查它,就像它无法为您求解任意方程一样。 NDR(不需要诊断)正是为这种情况而设计的——程序格式错误,如果编译器确实能够检测到,则需要进行诊断。 NDR 允许编译器不检查它。
When N is zero, the instantiation of the expansion produces an empty list. Such an instantiation does not alter the syntactic interpretation of the enclosing construct.
我们说的规则是语义规则,不是句法规则,因为句法规则是以[gram]为单位的。
那么 NDR 规则的基本原理是什么?一般来说,它们解决的问题在实施策略中是不可重现的。例如,它们可能会导致代码在某些实现策略中行为不当,但不会在其他方面造成任何问题(并且不容易)。
此外,请注意标准在程序方面使用 "ill-formed" 等术语。因此,谈论一个孤立代码片段的格式是否正确并不总是合理的。在这种情况下,std::enable_if
需要不特化,否则情况可能会变得更复杂。