Use string litterals in a "char type" templated class

I have a template class in C++ which takes as a char_type template parameter the character type, such as char , wchar_t , char32_t , etc... The class then use std::basic_string<char_type> in the code.

Then somewhere in the class I fill a table of escaping sequences such as "&amp;" . This does not work as depending on the template character type, we would need to use "&amp;" , L"&amp;" , U"&amp;" ...

Is there a way to avoid specializing the template functions for initializing the table, for instance with some standard function for converting string litterals?

As these are escaping sequences, they do not contain anything else than ASCII characters.


I would do the following:

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
}

You can use it this way:

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

I've tested it 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> >

Is untested for all the char types but hope it helps.

Edit 1

My bad, I just noticed that galinette almost answered the same as me before I did. The only difference between my code and the one from galinette is that I'm allocating the resulting string once with reserve instead of using the automatic allocation of push_back counting the number of characters at compile time, due to the use of LENGTH as a template parameter.

Edit 2

It is possible to avoid the final null character issue by substracting 1 to the end iterator:

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
}

Or, using std::copy_n instead of 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
}

最好的方法是自己定义转换函数,因为将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;
}

链接地址: http://www.djcxy.com/p/29452.html

上一篇: 枚举与javap反汇编不显示构造函数参数

下一篇: 在“char类型”模板类中使用字符串