字符串文字 - char 类型之间的模板转换
string literal - template conversion between char types
我想编写一个如下所示的函数:
template <typename CharT>
std::basic_string<CharT> convert(char const *);
并按如下方式使用:
convert<char>("Hello World!"); // "Hello World!"
convert<wchar_t>("Hello World!"); // L"Hello World!"
convert<char16_t>("Hello World!"); // u"Hello World!"
convert<char32_t>("Hello World!"); // U"Hello World!"
我可以使用 std::codecvt
和 co,但我发现它几乎毫无意义,因为使用一些添加 L
、u
或 [=16= 的宏会更容易] 0成本。
不幸的是,模板和宏的行为不在同一级别...所以我的问题来了:有什么方法可以混合它们吗?或者有更好的方法吗?
我的主要目标是避免重复(专业化)代码:我编写的一些函数是 CharT
模板化的并使用字符串文字,这将是唯一的区别。例如:
template <typename CharT>
void foo (std::vector<std::basic_string<CharT>> const & vec,
std::basic_string<CharT> str = convert<CharT>("default"));
这将避免为每种字符类型专门化 foo()。
非常感谢您的帮助
已编辑:这将从 C++11
开始工作。由于运算符不能是模板,您可以将运算符重载更改为 convert
函数。
#include <string>
std::basic_string<char> operator ""_s(const char * str, std::size_t len) {
return std::basic_string<char> (str, str + len);
}
std::basic_string<char16_t> operator ""_u(const char * str, std::size_t len) {
return std::basic_string<char16_t> (str, str + len);
}
std::basic_string<char32_t> operator ""_U(const char * str, std::size_t len) {
return std::basic_string<char32_t> (str, str + len);
}
std::basic_string<wchar_t> operator ""_L(const char * str, std::size_t len) {
return std::basic_string<wchar_t> (str, str + len);
}
int main() {
std::string s1 = "Hello World!"_s;
std::u16string s2 = "Hello World!"_u;
std::u32string s3 = "Hello World!"_U;
std::wstring s4 = "Hello World!"_L;
return 0;
}
查看LIVE DEMO 工作。
我终于想到了使用宏来生成函数 foo 的每 4 个重载。
template <typename CharT>
void foo (std::vector<std::basic_string<CharT>> const & vec,
std::basic_string<CharT> str = convert<CharT>("default"));
变成
#define FOO(CharT, prefix) \
void foo (std::vector<std::basic_string<CharT>> const & vec, \
std::basic_string<CharT> str = prefix ## "default");
我只需要添加
FOO(char, )
FOO(wchar_t, L)
FOO(char16_t, u)
FOO(char32_t, U)
我还可以将四行代码放入另一个宏 GENERATE 中,这样我就可以简单地调用
GENERATE(FOO)
我知道宏...但我已经达到了避免代码重复的主要目标。 :-)
感谢大家的帮助!
我想编写一个如下所示的函数:
template <typename CharT>
std::basic_string<CharT> convert(char const *);
并按如下方式使用:
convert<char>("Hello World!"); // "Hello World!"
convert<wchar_t>("Hello World!"); // L"Hello World!"
convert<char16_t>("Hello World!"); // u"Hello World!"
convert<char32_t>("Hello World!"); // U"Hello World!"
我可以使用 std::codecvt
和 co,但我发现它几乎毫无意义,因为使用一些添加 L
、u
或 [=16= 的宏会更容易] 0成本。
不幸的是,模板和宏的行为不在同一级别...所以我的问题来了:有什么方法可以混合它们吗?或者有更好的方法吗?
我的主要目标是避免重复(专业化)代码:我编写的一些函数是 CharT
模板化的并使用字符串文字,这将是唯一的区别。例如:
template <typename CharT>
void foo (std::vector<std::basic_string<CharT>> const & vec,
std::basic_string<CharT> str = convert<CharT>("default"));
这将避免为每种字符类型专门化 foo()。
非常感谢您的帮助
已编辑:这将从 C++11
开始工作。由于运算符不能是模板,您可以将运算符重载更改为 convert
函数。
#include <string>
std::basic_string<char> operator ""_s(const char * str, std::size_t len) {
return std::basic_string<char> (str, str + len);
}
std::basic_string<char16_t> operator ""_u(const char * str, std::size_t len) {
return std::basic_string<char16_t> (str, str + len);
}
std::basic_string<char32_t> operator ""_U(const char * str, std::size_t len) {
return std::basic_string<char32_t> (str, str + len);
}
std::basic_string<wchar_t> operator ""_L(const char * str, std::size_t len) {
return std::basic_string<wchar_t> (str, str + len);
}
int main() {
std::string s1 = "Hello World!"_s;
std::u16string s2 = "Hello World!"_u;
std::u32string s3 = "Hello World!"_U;
std::wstring s4 = "Hello World!"_L;
return 0;
}
查看LIVE DEMO 工作。
我终于想到了使用宏来生成函数 foo 的每 4 个重载。
template <typename CharT>
void foo (std::vector<std::basic_string<CharT>> const & vec,
std::basic_string<CharT> str = convert<CharT>("default"));
变成
#define FOO(CharT, prefix) \
void foo (std::vector<std::basic_string<CharT>> const & vec, \
std::basic_string<CharT> str = prefix ## "default");
我只需要添加
FOO(char, )
FOO(wchar_t, L)
FOO(char16_t, u)
FOO(char32_t, U)
我还可以将四行代码放入另一个宏 GENERATE 中,这样我就可以简单地调用
GENERATE(FOO)
我知道宏...但我已经达到了避免代码重复的主要目标。 :-)
感谢大家的帮助!