gpt4 book ai didi

c++ - 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数

转载 作者:行者123 更新时间:2023-12-03 10:04:39 25 4
gpt4 key购买 nike

看了之后the关于非类型模板参数的帖子,我对该帖子中的示例感到困惑,我在这里引用了示例:

struct VariableLengthString {
const char *data_ = nullptr;
constexpr VariableLengthString(const char *p) : data_(p) {}
auto operator<=>(const VariableLengthString&) const = default;
};

template<VariableLengthString S>
int bar() {
static int i = 0;
return ++i;
}

int main() {
int x = bar<"hello">(); // ERROR
}

帖子说“相关的措辞是[temp.arg.nontype]/2”,所以我看了一下那个规则,它限制了什么可以是非类型模板参数。

A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter.



所以,我看了一下 converted constant expression ,它的定义在这里:

A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression and the implicit conversion sequence contains only...



什么是常量表达式?这些规则在这里:

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

(2.2) an invocation of a function other than a constexpr constructor for a literal class, a constexpr function, or an implicit invocation of a trivial destructor.



那么,是类类型 VariableLengthString一个文字类?是的,它是。这里有什么规则可以证明:

A type is a literal type if it is:
1. possibly cv-qualified void; or
2. a scalar type; or
3. a reference type; or
4. an array of literal type; or
a possibly cv-qualified class type that has all of the following properties:

  1. it has a trivial destructor,
  2. it is either a closure type, an aggregate type, or has at least one constexpr constructor or constructor template (possibly inherited from a base class) that is not a copy or move constructor,
  3. if it is not a union, all of its non-static data members and base classes are of non-volatile literal types.


关键是,这些类型的对象是 VariableLengthString类型的子对象吗?所有文字类型?是否上课 VariableLengthString至少有一个 constexpr 构造函数?是的。因为这些规则:

Arithmetic types, enumeration types, pointer types, pointer to member types ([basic.compound]), std​::​nullptr_­t, and cv-qualified versions of these types are collectively called scalar types.



因此,子对象 data_ ,它是指针类型。因此,它是标量类型,也是文字类型。满足第 3 项。是否 constexpr VariableLengthString(const char *p) constexpr 构造函数?是的,它是,因为这些规则:

The definition of a constexpr constructor shall satisfy the following requirements:

  1. the class shall not have any virtual base classes;
  2. each of the parameter types shall be a literal type;
  3. every non-variant non-static data member and base class subobject shall be initialized


对于 constexpr VariableLengthString(const char *p) ,这三个规则都满足。综上所述,类 VariableLengthString是文字类型和类型为 VariableLengthString 的 constexpr 表达式可以用作非类型模板参数,因为它满足 的要求转换后的常量表达式 .为什么上面的代码格式错误?如果我遗漏了什么,请帮我找出它们。

最佳答案

代码格式错误,因为 the standard says so :

For a non-type template-parameter of reference or pointer type, or for each non-static data member of reference or pointer type in a non-type template-parameter of class type or subobject thereof, the reference or pointer value shall not refer to or be the address of (respectively):

...

  • a string literal

加了重点。 C++17 和之前的版本不允许您使用指向文字的指针作为 NTTP。因此,C++20 不允许您通过 NTTP 的类成员走私指向文字的指针。

关于c++ - 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65869351/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com