为不同的字符串类拟合字符串文字

Nie*_*ann 5 string templates literals prefix c++11

问题

我采取一个类,我希望让用户选择字符串类型(std::string,std::wstring,std::u16string通过模板参数,...).我目前无法使字符串文字符合所选的字符串类型:一旦我决定使用文字前缀("hello"vs. L"hello"vs. u"hello"vs. U"hello"),我会收到所有不兼容字符串类的编译错误.

玩具示例

作为示例,请考虑以下代码(编译--std=c++11):

#include <string>

template<typename StringType>
void hello_string()
{
    StringType result("hello");
}

int main()
{
    // works
    hello_string<std::string>();
    hello_string<std::basic_string<char>>();

    // the code below does not compile
    hello_string<std::wstring>();
    hello_string<std::basic_string<unsigned char>>();
    hello_string<std::u16string>();
}
Run Code Online (Sandbox Code Playgroud)

函数hello_string()显示了我想要做的事情的本质:将字符串类型作为模板参数,并将字符串文字分配给此类型的变量.

可能的解决方法

克服我的问题的一种方法是实现该hello_string()函数的几个特化.问题是,这将导致每个字符串文字的几个副本 - 每个字符串文字前缀一个.我认为这是相当丑陋的,必须有更好的方法.

另一种方法是选择"普通"字符串文字作为默认值,并让函数转换为不同的字符串类型.虽然这可以避免代码重复,但它会引入实际上不变的不必要的转换.

Dat*_*yte 2

你可以自己做一个宏。首先定义一个包装字符选择的结构:

namespace details {

    template<typename T>
    struct templ_text;

    template<>
    struct templ_text <char>
    {
        typedef char char_type;
        static const char_type * choose(const char * narrow, const wchar_t * wide, const char16_t* u16, const char32_t* u32) { return narrow; }
        static char_type choose(char narrow, wchar_t wide, char16_t u16, char32_t u32) { return narrow; }
    };

    template<>
    struct templ_text < wchar_t >
    {
        typedef wchar_t char_type;
        static const char_type* choose(const char * narrow, const wchar_t * wide, const char16_t* u16, const char32_t* u32) { return wide; }
        static char_type choose(char narrow, wchar_t wide, char16_t u16, char32_t u32) { return wide; }
    };

    template<>
    struct templ_text < char16_t >
    {
        typedef char16_t char_type;
        static const char_type* choose(const char * narrow, const wchar_t * wide, const char16_t* u16, const char32_t* u32) { return u16; }
        static char_type choose(char narrow, wchar_t wide, char16_t u16, char32_t u32) { return u16; }
    };

    template<>
    struct templ_text < char32_t >
    {
        typedef char32_t char_type;
        static const char_type* choose(const char * narrow, const wchar_t * wide, const char16_t* u16, const char32_t* u32) { return u32; }
        static char_type choose(char narrow, wchar_t wide, char16_t u16, char32_t u32) { return u32; }
    };
}
Run Code Online (Sandbox Code Playgroud)

将其包装成一个漂亮的宏:

#define TEMPL_TEXT(Ch, txt) details::templ_text<Ch>::choose(txt, L##txt, u##txt, U##txt)
Run Code Online (Sandbox Code Playgroud)

那么你的函数将是:

template<typename StringType>
void hello_string()
{
    StringType result(TEMPL_TEXT(typename StringType::value_type, "Hello"));
}
Run Code Online (Sandbox Code Playgroud)

我认为未使用的字符串副本将被优化掉。