非类型模板参数能否为"void *"类型? [英] Can a non-type template parameter be of type "void*"?

查看:270
本文介绍了非类型模板参数能否为"void *"类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Y牛-亚当·内夫罗蒙特 :

类型为void*的非类型模板参数不允许在 至少是该标准的某些版本.

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

这是真的吗? 如果为真,则在哪些版本的标准中不允许类型为void*的非类型模板参数?

Is this true? If it is true, in which versions of the standard are non-type template parameters of type void* not allowed?

(注意:如 评论 回答 另一条评论, 这是关于非类型模板参数的, 不是模板类型参数, 可以是每个有效的 type-id [temp.arg.type] , 包括void*.

(Note: as noted in a comment to answer another comment, this is about non-type template parameters, not template type arguments, which can be any valid type-id per [temp.arg.type], including void*.

推荐答案

TL; DR

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

TL;DR

Template parameters of type void* are valid since C++20. They are invalid prior to C++20.

C ++ 20放宽了对非类型模板参数类型的限制, 因此,我们首先对其进行调查.

C++20 relaxed the restrictions on the type of a non-type template parameter, so let's investigate it first.

当前草案(截至UTC 2019年5月6日10:00)在

The current draft (as of UTC 10:00, May 6, 2019) says in [temp.param]/4:

非类型 template-parameter 必须具有以下之一 (可选,具有简历资格)类型:

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

  • 具有强结构等式([class.compare.default])的文字类型,
  • 左值引用类型
  • 包含占位符类型([dcl.spec.auto])的类型,或
  • 推论类类型([dcl.type.class.deduct])的占位符.
  • 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*是指针类型. 指针类型是标量类型( [基本.types]/9 ). 标量类型文字类型(

void* is a pointer type. A pointer type is a scalar type ([basic.types]/9). A scalar type is a literal type ([basic.types]/10). Therefore, void* is a literal type. The first bullet is the relevant one.

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

如果给定的全值x,则类型C具有强烈的结构相等性 键入const C,或者:

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

  • C是非类类型,x <=> x是类型std::strong_orderingstd::strong_equality

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

C是具有==运算符的类类型,该运算符在C的定义中默认定义,x == x在上下文中格式正确 转换为bool的所有C基类子对象,并且都是非静态的 数据成员具有很强的结构相等性,并且C没有mutablevolatile子对象.

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 :

void* is a non-class type, so the first bullet is relevant. Now the question boils down to the type of x <=> x where x is a glvalue of type void* const (not const void*). Per [expr.spaceship]/8:

如果复合指针类型为对象指针类型,则p <=> q为 类型为std::strong_­ordering.如果两个指针操作数pq 比较等于([expr.eq]),p <=> q收益 std::strong_­ordering::equal;如果pq比较不相等,则p <=> q得出std::strong_­ordering::less如果q比较大于 pstd::strong_­ordering::greater,如果p比较大于 q([expr.rel]).否则,结果将不确定.

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*对象指针类型((

Note that void* is an object pointer type ([basic.compound]/3). Therefore, x <=> x is of type std::strong_ordering. Thus the type void* has strong structural equality.

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

Therefore, in the current C++20 draft, void* is allowed as the type of a template parameter type.

现在,我们解决C ++ 17问题. [temp.param] 说:

Now we address C++17. [temp.param] says:

非类型 template-parameter 必须具有以下之一 (可选,具有简历资格)类型:

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

  • 整数或枚举类型
  • 指向对象的指针或指向函数的指针,
  • 对对象的左值引用或对函数的左值引用,
  • 成员的指针,
  • std​::​nullptr_­t
  • 包含占位符类型的类型.
  • 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 that "pointer to object" doesn't include void* per [basic.compound]/3:

[注意:"指向void的指针没有指针到对象的类型,因为void不是对象类型. — 尾注]

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

以上六个项目符号均不包含void* 作为模板参数的可能类型. 因此,在C ++ 17中, 模板参数的类型不得为void*.

None of the above six bullets include void* as a possible type of a template parameter. Therefore, in C++17, a template parameter shall not have type void*.

C ++ 11和C ++ 14的措辞相同 除了不存在有关占位符类型的项目符号. 一般来说, 在C ++ 20之前, 模板参数的类型不得为void*.

The wording is the same for C++11 and C++14 except that the bullet about placeholder types are not there. In general, prior to C++20, a template parameter shall not have type void*.

T.C. 评论 没有人诊断出这个IHRC. 让我们测试一下编译器是否在C ++ 17模式下进行诊断 并显示以下最小示例:

T.C. says in a comment that nobody diagnoses this IHRC. Let's test whether compilers diagnose that in C++17 mode with the minimal example shown below:

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 C 8.0.0 C 7.0.0 C 6.0.1 , 和 C 5.0.0 .

The code compiles and runs fine on 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, and Clang 5.0.0.

NathanOliver

NathanOliver told me in a comment that someone told him some compilers will error, but the major ones don't. Therefore, as far as I am able to confirm here, T.C.'s statement is correct — nobody diagnoses this.

这篇关于非类型模板参数能否为"void *"类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆