+-
c – 非类型模板参数可以是“void *”类型吗?
Yakk – Adam Nevraumont
said:

Non-type template parameters of type void* are not allowed in at
least some versions of the standard.

这是真的?
如果是,那么标准的哪个版本是不允许的类型为void *的非类型模板参数?

(注:如中所述)
a comment
回答
another comment,
这是关于非类型模板参数,
不是模板类型参数,
可以是任何有效的type-id per
[temp.arg.type],
包括void *.

最佳答案
TL; DR

类型为void *的模板参数自C 20起有效.
它们在C 20之前无效.

C 20

C 20放宽了对非类型模板参数类型的限制,
所以我们先来调查吧.

目前的草案(截至2019年5月6日UTC 10:00)在[temp.param]/4中说:

A non-type template-parameter shall have one of the following
(optionally cv-qualified) types:

a literal type that has strong structural equality ([class.compare.default]), an lvalue reference type, a type that contains a placeholder type ([dcl.spec.auto]), or a placeholder for a deduced class type ([dcl.type.class.deduct]).

void *是指针类型.
指针类型是标量类型([basic.types]/9).
标量类型是文字类型([basic.types]/10).
因此,void *是文字类型.
第一颗子弹是相关的.

进一步追踪,[class.compare.default]/3说:

A type C has strong structural equality if, given a glvalue x of
type const C, either:

C is a non-class type and x <=> x is a valid expression of type std::strong_ordering or std::strong_equality, or

C is a class type with an == operator defined as defaulted in the definition of C, x == x is well-formed when contextually
converted to bool, all of C‘s base class subobjects and non-static
data members have strong structural equality, and C has no mutable
or volatile subobjects.

void *是非类型的,
所以第一颗子弹是相关的.
现在问题归结为x< =>的类型. X
其中x是void * const类型的glvalue(不是const void *).
每[expr.spaceship]/8:

If the composite pointer type is an object pointer type, p <=> q is
of type std::strong_­ordering. If two pointer operands p and q
compare equal ([expr.eq]), p <=> q yields
std::strong_­ordering::equal; if p and q compare unequal, p <=>
q
yields std::strong_­ordering::less if q compares greater than
p and std::strong_­ordering::greater if p compares greater than
q ([expr.rel]). Otherwise, the result is unspecified.

请注意,void *是对象指针类型([basic.compound]/3).
因此,x< => x的类型为std :: strong_ordering.
因此,类型void *具有强烈的结构相等性.

因此,在目前的C 20草案中,
允许void *作为模板参数类型的类型.

C 17

现在我们解决C 17.
[temp.param]说:

A non-type template-parameter shall have one of the following
(optionally cv-qualified) types:

integral or enumeration type, pointer to object or pointer to function, lvalue reference to object or lvalue reference to function, pointer to member, std​::​nullptr_­t, or a type that contains a placeholder type.

请注意,“指向对象的指针”不包含void *
每[basic.compound]/3:

[ Note: A pointer to void does not have a pointer-to-object type, however, because void is not an object type. — end note ]

上述六发子弹中没有一个包含空*
作为模板参数的可能类型.
因此,在C 17中,
模板参数的类型不能为void *.

对于C 11和C 14,措辞是相同的
除了关于占位符类型的子弹不在那里.
一般来说,
在C 20之前,
模板参数的类型不能为void *.

但是编译器会诊断出来吗?

T.C.在一篇文章中说
comment
没有人诊断出这个IHRC.
让我们测试编译器是否在C 17模式下诊断出来
使用如下所示的最小示例:

template <void*>
class C {};

int main()
{
    C<nullptr> x;
    (void) x;
}

代码编译并运行良好
GCC 9.1.0,
GCC 8.3.0,
GCC 7.3.0,
GCC 6.3.0,
GCC 5.5.0,
Clang 8.0.0,
Clang 7.0.0,
Clang 6.0.1,
和Clang 5.0.0.

NathanOliver在comment告诉我,有人告诉他一些编译器会出错,但主要的不会.因此,据我所知,T.C.的陈述是正确的 – 没有人诊断出这一点.

点击查看更多相关文章

转载注明原文:c – 非类型模板参数可以是“void *”类型吗? - 乐贴网