O'Neil
O'Neil

Reputation: 3849

string literal - template conversion between char types

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

Upvotes: 1

Views: 554

Answers (2)

O&#39;Neil
O&#39;Neil

Reputation: 3849

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!

Update

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"));

Upvotes: 0

Shreevardhan
Shreevardhan

Reputation: 12651

Edited: This will work from C++11. Since operator cannot be template you can change the operator overload to your convert function.

#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;
}

See LIVE DEMO working.

Upvotes: 0

Related Questions