Create strings depending on template arguments
I have many clas开发者_开发问答ses/methods like this:
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
struct Foo
{
std::basic_string<CharT, TraitsT> getFoo(void) const
{
return "Foo"; // + this->member_var1 + this->member_var2...
}
};
But depending on CharT, I have to use "", L"", u"" or "U" (for char, wchar_t, u16char_t, u32char_t).
What syntax must be used to create strings that are independed from such template arguments?
Do you really need the different literals, or can you use the iterator constructor?
const char *f = "Foo";
return std::basic_string<CharT, TraitsT>(f, f + 3);
Maybe with something a bit more robust than "3" in there, if you're worried about ease of changing the literal in future.
In response to the point that this isn't very nice, what about:
template <typename CharT, typename TraitsT, size_t N>
basic_string<CharT, TraitsT> proper_string(const char (&src)[N]) {
return basic_string<CharT, TraitsT>(src, src+N-1);
}
Then you have:
return proper_string<CharT, TraitsT>("Foo");
If you really need the different literal, then the only thing I've thought of so far is to create traits for it, which is really horrible:
template<typename T> struct FooString {
};
template<> struct FooString<char> {
static const char *value() { return "Foo"; }
};
template<> struct FooString<wchar_t> {
static const wchar_t *value() { return L"Foo"; }
};
... etc ...
return FooString<CharT>::value();
If you're going to be appending things to the string anyhow, use a stringstream:
std::basic_string<CharT, TraitsT> getFoo(void) const
{
std::basic_ostringstream<CharT, TraitsT> os;
os << "Foo";
// os << this->member_var1 << this->member_var2...
return os.str();
}
I like Steve Jessop's answer, too.
Here is a solution using a MACRO
template < typename CharT >
struct char_t_literal_selector;
template <>
struct char_t_literal_selector< char > {
static const char *select( const char *s, const wchar_t *, const char16_t *, const char32_t * )
{
return s;
}
};
template <>
struct char_t_literal_selector< wchar_t > {
static const wchar_t *select( const char *, const wchar_t *s, const char16_t *, const char32_t * )
{
return s;
}
};
template <>
struct char_t_literal_selector< char16_t > {
static const char16_t *select( const char *, const wchar_t *, const char16_t *s, const char32_t * )
{
return s;
}
};
template <>
struct char_t_literal_selector< char32_t > {
static const char32_t *select( const char *, const wchar_t *, const char16_t *, const char32_t *s )
{
return s;
}
};
#define CHART_LITERAL(str) ( char_t_literal_selector< CharT >::select( str, L ## str, u ## str, U ## str ) )
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
struct Foo
{
std::basic_string<CharT, TraitsT> getFoo(void) const
{
return CHART_LITERAL("Foo"); // + this->member_var1 + this->member_var2...
}
};
assuming the template parameter name is always CharT
. If it is not, add another parameter to the macro. HTH
精彩评论