在“char类型”模板化类中使用字符串litterals

时间:2015-09-29 09:22:59

标签: c++ templates widechar

我在C ++中有一个模板类,它将char_type模板参数作为字符类型,例如charwchar_tchar32_t等...然后在类中使用std::basic_string<char_type>

然后在课堂的某个地方填写一个表格,例如"&amp;"。这不能取决于模板字符类型,我们需要使用"&amp;"L"&amp;"U"&amp;" ...

有没有办法避免专门化模板函数来初始化表格,例如使用一些标准函数来转换字符串文字?

由于这些是转义序列,因此它们不包含除ASCII字符以外的任何内容。

5 个答案:

答案 0 :(得分:4)

我会做以下事情:

template <typename char_type, size_t LENGTH>
constexpr std::basic_string<char_type> literal(const char (&value)[LENGTH])
{
    using string = std::basic_string<char_type>;

    string result{};
    result.reserve(LENGTH);

    std::copy(std::begin(value), std::end(value), std::back_inserter(result));

    return result; // rvo
}

你可以这样使用它:

// Table of escaping sequences
std::basic_string<char_type> escaping_sequences[] =
{
    literal<char_type>("&amp"),
    literal<char_type>("&foo"),
    literal<char_type>("&bar"),
    ...
}

我测试了它in Ideone

literal<  char  >("test") // result: std::string
literal<char32_t>("test") // result: std::basic_string<char32_t, std::char_traits<char32_t>, std::allocator<char32_t> >
literal<char16_t>("test") // result: std::basic_string<char16_t, std::char_traits<char16_t>, std::allocator<char16_t> >

对所有字符类型都未经测试,但希望它有所帮助。

编辑1

我的不好,我只是注意到galinette在我做之前几乎和我一样回答。我的代码与来自galinette的代码之间的唯一区别是我使用reserve分配结果字符串一次而不是使用push_back 的自动分配来计算数字由于使用LENGTH作为模板参数,编译时的字符。

编辑2

通过将1减去end迭代器,可以避免最终的空字符问题:

template <typename char_type, size_t LENGTH>
constexpr std::basic_string<char_type> literal(const char (&value)[LENGTH])
{
    using string = std::basic_string<char_type>;

    string result{};
    result.reserve(LENGTH - 1);

    std::copy(std::begin(value), std::end(value) - 1, std::back_inserter(result));

    return result; // rvo
}

或者,使用std::copy_n代替std::copy

template <typename char_type, size_t LENGTH>
constexpr std::basic_string<char_type> literal(const char (&value)[LENGTH])
{
    using string = std::basic_string<char_type>;

    string result{};
    result.reserve(LENGTH - 1);

    std::copy_n(std::begin(value), LENGTH - 1, std::back_inserter(result));

    return result; // rvo
}

答案 1 :(得分:2)

最好的方法是自己定义转换函数,因为将ASCII转换为UTF8 / 16/32是对char类型的直接转换

template<typename char_type>
std::basic_string<char_type> cvtASCIItoUTFX(const char * litteral)
{
    //We could define a faster specialization in case char_type is char

    size_t s = strlen(litteral);

    std::basic_string<char_type> result;
    result.reserve(s);
    for(size_t i=0;i<s;++i)
    {
        result.push_back((char_type)litteral[i]);
    }

    return result;
}

答案 2 :(得分:1)

  

由于这些是转义序列,因此它们不包含除ASCII字符以外的任何内容。

     

有没有办法避免专门化模板函数来初始化表格,例如使用一些标准函数来转换字符串文字?

不,因为标准没有任何坚持这些特定子集的转换函数。

我建议只为表使用外部生成器,或者如果你真的想保持在C ++中,则使用宏。

答案 3 :(得分:0)

此答案仅适用于非字符串(即数字)文字

...因为只有那些被语言扩展到template<char...>

由于我已经花了一段时间,我想我也可以在这里发布。不适用于实际的字符文字,因为 herp derp C ++

template<char16_t... str>
struct Literal16 {
    static constexpr char16_t arr[] = {str...};

    constexpr operator const char16_t*() { 
        return arr;
    }
};

template<char... str>
struct Literal8 {
    static constexpr char arr[] = {str...};

    constexpr operator const char*() { 
        return arr;
    }
};

template<char... str>
struct PolyLiteral {
    operator const char*() {
        return Literal8<str...>();
    }
    operator const char16_t*() {
        return Literal16<str...>();
    }  
};

template<char... str> PolyLiteral<str...> operator"" _poly() { return PolyLiteral<str...>(); }

int main() {
    const char* test = 123_poly;
    const char16_t* test2 = 123_poly;
}

答案 4 :(得分:-4)

如果你可以使用宏:

#define TEXT_char(text) (text)
#define TEXT_wchar_t(text) (L ## text)
//...etc
#define TEXT(type, text) (TEXT_##type(text))

int main() 
{
    const char* c = TEXT(char, "Test");
    const wchar_t* w = TEXT(wchar_t, "Test");
}