I would like to code a function that would look like:
template <typename CharT>
std::basic_string<CharT> convert(char const *);
and be used as follows:
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!"
I could use std::codecvt
and co, but I find it almost pointless as it would be so easier to use some macro that adds L
, u
or U
with 0 cost.
Unfortunately templates and macros don't act at the same level... So here comes my question: would there be some way to mix them ? Or is there a better way ?
My main goal is to avoid repetition (specialization) of code: some functions I'm coding are CharT
templated and use string literals, and that would be the only difference. As an example:
template <typename CharT>
void foo (std::vector<std::basic_string<CharT>> const & vec,
std::basic_string<CharT> str = convert<CharT>("default"));
That would avoid to specialize foo() for each char type.
Many thanks for your help
I finally got the idea of using macros to generate every 4 overloads of the function foo.
template <typename CharT>
void foo (std::vector<std::basic_string<CharT>> const & vec,
std::basic_string<CharT> str = convert<CharT>("default"));
becomes
#define FOO(CharT, prefix) \
void foo (std::vector<std::basic_string<CharT>> const & vec, \
std::basic_string<CharT> str = prefix ## "default");
and I just have to add
FOO(char, )
FOO(wchar_t, L)
FOO(char16_t, u)
FOO(char32_t, U)
four lines that I can also put into another macro GENERATE so I can simply call
GENERATE(FOO)
I know macros... but I've reached my main goal to avoid code repetition. :-)
Thanks everybody for your help!
After reading the paper Formatting Ranges and the mention of "STATICALLY-WIDEN", I finally have:
template <typename CharT>
constexpr auto statically_widen(
#ifdef __cpp_char8_t
const char8_t * u8str,
#endif
const char16_t* u16str,
const char32_t* u32str,
const char * str,
const wchar_t* wstr
) {
if constexpr (std::is_same<CharT, char>::value)
return str;
else if constexpr (std::is_same<CharT, wchar_t>::value)
return wstr;
#ifdef __cpp_char8_t
else if constexpr (std::is_same<CharT, char8_t>::value)
return u8str;
#endif
else if constexpr (std::is_same<CharT, char16_t>::value)
return u16str;
else if constexpr (std::is_same<CharT, char32_t>::value)
return u32str;
}
#ifdef __cpp_char8_t
#define STATICALLY_WIDEN(CharT, str) statically_widen<CharT>(u8##str, u##str, U##str, str, L##str)
#else
#define STATICALLY_WIDEN(CharT, str) statically_widen<CharT>(u##str, U##str, str, L##str)
#endif
template <typename CharT>
void foo (std::vector<std::basic_string<CharT>> const & vec,
std::basic_string<CharT> str = STATICALLY_WIDEN(CharT, "default"));