2010-11-04 7 views
14

tengo muchos clases/métodos como éste:crear cadenas en función de argumentos de plantilla

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... 
    } 
}; 

Pero dependiendo de la carta, tengo que usar "" L "" U "" o "U" (para char, wchar_t, u16char_t, u32char_t).

¿Qué sintaxis debe usarse para crear cadenas independientes de tales argumentos de plantilla?

+1

Buena pregunta ... –

Respuesta

7

¿Realmente necesita los diferentes literales, o puede usar el constructor del iterador?

const char *f = "Foo"; 
return std::basic_string<CharT, TraitsT>(f, f + 3); 

Tal vez con algo un poco más robusto que "3" allí, si le preocupa la facilidad de cambiar el literal en el futuro.

En respuesta a tal punto que esto no es muy agradable, ¿qué pasa con:

entonces usted tiene:

return proper_string<CharT, TraitsT>("Foo"); 

Si realmente necesita la diversa, entonces lo único literal he pensado hasta ahora es crear rasgos de ella, que es realmente abrasador

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(); 
+1

Use una matriz de caracteres en lugar de un puntero para const char, y use 'sizeof f' en su lugar. – dreamlax

+1

'const char f [] =" Foo "; return std :: basic_string (f, f + sizeof f) ' – dreamlax

+0

Crear a partir de dos iteradores es una solución alternativa, pero no es una buena solución para muchas situaciones similares. – cytrinox

1

Si vas a estar añadiendo cosas a la cadena en cualquier caso, utilice un 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(); 
} 

me gusta la respuesta de Steve Jessop, también.

1

Aquí es una solución utilizando una 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... 
    } 
}; 

suponiendo que el nombre de parámetro de plantilla es siempre CharT. Si no es así, agregue otro parámetro a la macro. HTH

+0

Esto es mejor que mi solución para obtener el literal (creo), pero no estoy seguro si el literal es realmente necesario, o simplemente el 'basic_string'. –

Cuestiones relacionadas