Use string litterals in char type pattern

I have a template class in C ++ that takes char_type as a template char_type a character type like char , wchar_t , char32_t etc. Then the class uses std::basic_string<char_type> in the code.

Then, somewhere in the class, I populate the escape sequence table, for example, "&amp;" . This does not work depending on the type of character pattern, we will need to use "&amp;" , L"&amp;" , U"&amp;" ...

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

Since these are escape sequences, they contain nothing but ASCII characters.

+7
c ++ templates widechar
source share
5 answers

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 as follows:

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

I 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> > 

Not tested for all char types, but hope this helps.

Change 1

My bad one, I just noticed that the galinette answered almost the same way as I did. The only difference between my code and one of galinette is that I distribute the received string once using reserve instead of automatically distributing push_back by counting the number of characters at compile time, due to the use of LENGTH as a template parameter.

Edit 2

You can avoid the final null character error by subtracting 1 in the 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 } 
+4
source share

The best way is perhaps to define a conversion function, since converting ASCII to UTF8 / 16/32 is a simple choice of char types

 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
source share

Since these are escape sequences, they contain nothing but ASCII characters.

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

No, because the standard does not have any conversion functions that adhere to such specific subsets.

I would recommend using an external generator for the table, or if you really want to stay in C ++, use macros.

+1
source share

This answer only works for non-line (i.e. numeric) literals

... because only those expand to template<char...> using the language.

Since I spent some time on this, I decided that I could post it here. Doesn't work with actual character literals, because 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; } 
0
source share

If you use macros:

 #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"); } 
-4
source share

All Articles