了解 c++20 的用户定义字符串文字加法
understanding user defined string literals addition for c++20
我在 user defined string literal 中找到以下内容:
- 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 终止符作为数组的一部分。
我在 user defined string literal 中找到以下内容:
- 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 终止符作为数组的一部分。