理解 c++20 的用户定义字符串文字加法

Kla*_*aus 2 c++ user-defined-literals c++20

我在用户定义的字符串文字中发现以下内容:

  1. 对于用户定义的字符串文字,令 str 为不带 ud 后缀的文字:

a) 如果重载集包含带有非类型模板参数的字符串文字运算符模板,其中 str 是格式良好的模板参数,则用户定义的文字表达式将被视为函数调用operator "" X<str>()

这对我来说听起来有点神秘。有人可以举例说明如何使用它吗?

以下根本不起作用,我无法理解非类型模板参数的意义MyType。它似乎不是 char* 也不是 const char*:

template < ??? >
struct MyType 
{
    const char* c;
    constexpr MyType( const char* in ): c{in}{}
};

template < MyType t > auto operator ""_y() { return t; }

int main()
{
    "Check it"_y;
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*las 5

这是令人困惑的措辞,它是直接从标准复制的

如果[重载集]包含带有非类型模板参数的文字运算符模板,该模板参数str是格式良好的模板参数

令人困惑的一点是“格式str良好的模板参数”具体适用于什么问题。直接阅读标准中的段落表明“forwhich”指的是“非类型模板参数”,因为这是直接在“forwhich”之前的文本。但是,如果您查看标准如何调用该函数,您会看到以下内容:

operator "" X<str>()
Run Code Online (Sandbox Code Playgroud)

str被传递给运算符,这意味着将在str“非类型模板参数”之间发生隐式转换。也就是说,是重载函数str的有效“模板参数” ,而不是重载函数的模板参数。因此,“for which”部分应该指的是“带有非类型模板参数的文字运算符模板”,而不是“非类型模板参数”。

话虽如此,为了使您的代码正常工作,您需要做的不仅仅是从 中删除模板参数MyType

您可能已经注意到 C++ 中围绕非类型模板参数 (NTTP) 的某些奇怪之处。例如,NTTP 始终能够成为指向事物的指针。但你永远不能这样做:

template<const char *literal> void foo() {}
foo<"literal">();
Run Code Online (Sandbox Code Playgroud)

该标准明确禁止使用字符串文字初始化指针 NTTP。而 C++20 并没有改变这一点

因此,你不能接受指针。您必须了解字面量的实际含义:一个数组。但是你也不能通过作为const char (&in)[]参数来使你的代码工作。文字不是未调整大小的数组(因为“未调整大小的数组”不是真正的对象类型)。该数组参数的大小必须适合文字。

这意味着您必须从尺寸模板参数中推断出尺寸。

此外,其他规则完全禁止您在 NTTP 中(直接或间接)存储指向字符串文字的指针。因此,如果您想要一个在 NTTP 中表示整个字符串文字的类型,则该 NTTP 类型必须包含一个大小等于该大小的数组。

因此,您可以构建的最简单的函数字符串文字 NTTP

template<size_t N>
struct string_literal
{
    std::array<char, N> arr_;

    constexpr string_literal(const char(&in)[N]) : arr_{}   
    {
        std::copy(in, in + N, arr_.begin());
    }
};
Run Code Online (Sandbox Code Playgroud)

借助 CTAD,您只需使用它template < string_literal t > auto operator ""_y()来定义您的 UDL。

请注意,此类string_literal明确包含 NUL 终止符作为数组的一部分。