templates - Fitting string literals for different string classes -
the problem
i implementing class want let user choose string type (std::string, std::wstring, std::u16string, ...) via template parameter. fail make string literals fit chosen string type: once decide literal prefix ("hello" vs. l"hello" vs. u"hello" vs. u"hello"), compilation errors incompatible string classes.
toy example
as example, consider following code (compile --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>>(); // code below not compile hello_string<std::wstring>(); hello_string<std::basic_string<unsigned char>>(); hello_string<std::u16string>(); } function hello_string() shows essence of want do: have string type template parameter, , assign string literals variables of type.
possible workaround
one way overcome problem implement several specializations of hello_string() function. problem lead several copies of each string literal - 1 each string literal prefix. think rather ugly, , there must better way.
another way chose "normal" string literals default values , have functions conversion different string types. while avoid code duplication, introduce unnecessary conversions of constant.
you can make macro. first define struct wraps char-choosing:
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; } }; } wrap nice macro:
#define templ_text(ch, txt) details::templ_text<ch>::choose(txt, l##txt, u##txt, u##txt) then function be:
template<typename stringtype> void hello_string() { stringtype result(templ_text(typename stringtype::value_type, "hello")); } i think unused copies of string optimized away.
Comments
Post a Comment