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

understanding user defined string literals addition for c++20

我在 user defined string literal 中找到以下内容:

  1. For user-defined string literals, let str be the literal without ud-suffix:

a) If the overload set includes a string literal operator template with a non-type template parameter for which str is a well-formed template argument, then the user-defined literal expression is treated as a function call 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;
}

这是令人困惑的措辞,copied directly from the standard:

If [the overload set] contains a literal operator template with a non-type template parameter for which str is a well-formed template-argument

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

operator "" X<str>()

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

话虽如此,要让您的代码正常工作,您需要做的不仅仅是从 MyType.

中删除模板参数

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

template<const char *literal> void foo() {}
foo<"literal">();

标准明确禁止用字符串文字初始化指针 NTTP。而 C++20 不会改变这个

因此,不能拿指针。您必须采用文字实际是什么:一个数组。但是你也不能通过将 const char (&in)[] 作为参数来使你的代码工作。文字不是未调整大小的数组(因为“未调整大小的数组”不是真实的对象类型)。该数组参数 的大小 必须适合文字。

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

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

所以最简单的函数式字符串文字 NTTP you could build would be:

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());
    }
};

感谢 CTAD,您只需使用 template < string_literal t > auto operator ""_y() 即可定义您的 UDL。

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