这是一个令人困惑的措辞,它是copied directly from the standard:
如果 [重载集] 包含带有非类型模板参数的文字运算符模板,而 str 是一个格式良好的模板参数
令人困惑的是“str 是一个格式良好的模板参数”具体适用于什么的问题。直接阅读标准中的段落表明“for which”指的是“非类型模板参数”,因为这是直接在“for which”之前的文本。但是,如果您查看标准如何说明该函数将被调用,您会看到:
operator "" X<str>()
str 被传递给操作员,这意味着在str 和“非类型模板参数”之间将发生隐式转换。也就是说,str 是 重载函数 的有效“模板参数”,而不是重载函数的模板参数。因此,“for which”部分应该指的是“带有非类型模板参数的文字运算符模板”,而不是“非类型模板参数”。
话虽如此,要使您的代码正常工作,您需要做的不仅仅是从 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 类明确包含 NUL 终止符作为数组的一部分。