是否可以为字符串文字创建模板化的用户定义文字(文字后缀)? [英] Is it possible to create templated user-defined literals (literal suffixes) for string literals?
问题描述
当我发现可以将用户定义的文字模板化时,我感到很惊讶:
I was suprised when I discovered that it's possible to make user-defined literals templated:
template <char ...C> std::string operator ""_s()
{
char arr[]{C...};
return arr;
}
// ...
std::cout << 123_s;
但以上声明不适用于字符串文字:
But above declaration does not work with string literals:
"123"_s
给我以下错误:
prog.cpp: 在函数int main()"中:
prog.cpp:12:15: 错误:没有用于调用operator"_s()"的匹配函数
std::cout <<"123"_s;
prog.cpp: In function 'int main()':
prog.cpp:12:15: error: no matching function for call to 'operator""_s()'
std::cout << "123"_s;
prog.cpp:4:34: 注意:候选:模板 std::string operator""_s()
模板 std::string 运算符 ""_s()
prog.cpp:4:34: note: candidate: template std::string operator""_s()
template std::string operator ""_s()
prog.cpp:4:34: 注意:模板参数推导/替换失败:
prog.cpp:4:34: note: template argument deduction/substitution failed:
有没有办法将模板化的用户定义文字也与字符串文字一起使用?
Is there is a way to use templated user-defined literals with string literals as well?
推荐答案
Pre-C++20 在标准 C++ 中是不可能的.有关适用于 GCC 和 Clang 的非标准解决方案,请参阅@T.C. 的答案.
Pre-C++20 it's impossible in standard C++. Refer to @T.C.'s answer for a non-standard solution that works with GCC and Clang.
从 C++20 开始,您可以将字符串文字作为模板参数传递.你需要一个这样的辅助类:
Starting with C++20, you can pass string literals as template parameters. You need a helper class like this one:
#include <algorithm>
#include <cstddef>
#include <string_view>
namespace impl
{
// Does nothing, but causes an error if called from a `consteval` function.
inline void ExpectedNullTerminatedArray() {}
}
// A string that can be used as a template parameter.
template <std::size_t N>
struct ConstString
{
char str[N]{};
static constexpr std::size_t size = N - 1;
[[nodiscard]] std::string_view view() const
{
return {str, str + size};
}
consteval ConstString() {}
consteval ConstString(const char (&new_str)[N])
{
if (new_str[N-1] != '\0')
impl::ExpectedNullTerminatedArray();
std::copy_n(new_str, size, str);
}
};
它允许你这样做:
#include <iostream>
template <ConstString S>
void Print()
{
std::cout << S.view() << '\n';
}
int main()
{
Print<"foo">();
}
这对于您的用例来说可能就足够了,而且您可能不需要模板 UDL 本身.
This might be enough for your use case, and you might not need template UDLs per se.
但如果您确实需要它们,那是可能的:
But if you do need them, it's possible:
#include <iostream>
template <ConstString S>
void operator""_print()
{
std::cout << S.view();
}
int main()
{
"foo"_print;
}
这篇关于是否可以为字符串文字创建模板化的用户定义文字(文字后缀)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!