看完有关非类型模板参数的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:
- it has a trivial destructor,
- 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,
- 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:
- the class shall not have any virtual base classes;
- each of the parameter types shall be a literal type;
- 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, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
... * a string literal
表达式是否为常量表达式并不重要。您不能将指向字符串文字的指针用作非类型模板参数(NTTP)。而且,将用户定义类型作为NTTP的建议不会对此进行更改,因此您不能在NTTP中隐藏指向字符串文字的指针,并且仍然希望它能够正常工作。
关于c++ - 为什么带有指针子对象的文字类类型的constexpr表达式不能是非类型模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61838757/