2010-11-04 3 views
14

j'ai beaucoup classes/méthodes comme celle-ci:Créer des chaînes en fonction des arguments de modèle

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

Mais selon CHART, je dois utiliser "", L "", u "" ou "U" (pour char, wchar_t, u16char_t, u32char_t).

Quelle syntaxe doit être utilisée pour créer des chaînes indépendantes de ces arguments de modèle?

+1

Bonne question ... –

Répondre

7

Avez-vous vraiment besoin des différents littéraux, ou pouvez-vous utiliser le constructeur itérateur? Peut-être avec quelque chose d'un peu plus robuste que "3" là-bas, si vous êtes inquiet de la facilité de changer le littéral à l'avenir.

En réponse au point que ce n'est pas très agréable, qu'en est:

Ensuite, vous avez:

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

Si vous avez vraiment besoin de l'autre littéral, alors la seule chose J'ai pensé à ce jour est de créer des traits pour elle, ce qui est vraiment 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(); 
+1

Utilisez un tableau de caractères à la place d'un pointeur vers constchar et utilisez 'sizeof f' à la place. – dreamlax

+1

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

+0

La création à partir de deux itérateurs est une solution de contournement, mais pas une bonne solution pour de nombreuses situations de ce type. – cytrinox

1

Si vous allez être des choses à la annexant chaîne en tout cas, utilisez 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(); 
} 

J'aime la réponse de Steve Jessop, aussi.

1

Voici une solution en utilisant une 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... 
    } 
}; 

en supposant que le nom du paramètre du modèle est toujours CharT. Si ce n'est pas le cas, ajoutez un autre paramètre à la macro. HTH

+0

C'est mieux que ma solution pour obtenir le littéral (je pense), mais je ne suis pas sûr si le littéral est réellement nécessaire, ou juste le 'basic_string'. –

Questions connexes