简体   繁体   中英

Create strings depending on template arguments

I have many classes/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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM