2010-11-04 4 views
14

Я имею много классов/методов, как это:Создание строк в зависимости от аргументов шаблона

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

Но в зависимости от чарта, я должен использовать «», L «», и «» или «U» (для char, wchar_t, u16char_t, u32char_t).

Какой синтаксис должен использоваться для создания строк, которые не зависят от таких аргументов шаблона?

+1

Хороший вопрос ... –

ответ

7

Вам действительно нужны разные литералы, или вы можете использовать конструктор итератора?

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

Может быть, с чем-то немного более надежным, чем «3» там, если вы беспокоитесь о легкости изменения буквального в будущем.

В ответ на точку, что это не очень приятно, что о:

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

Тогда у вас есть:

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

Если вам действительно нужно другое буквальное, то единственное, Я думал, что так далеко, чтобы создать для него черты, что действительно ужасны:

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

Используйте массив символов вместо указателя на const char и вместо этого используйте 'sizeof f'. – dreamlax

+1

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

+0

Создание из двух итераторов является обходным решением, но не хорошим решением для многих подобных ситуаций. – cytrinox

1

Если вы собираетесь быть добавление вещи в строку, так или иначе, использовать 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(); 
} 

Мне нравится ответ Стива Джессопа, тоже.

1

Вот решение с помощью 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... 
    } 
}; 

предполагая имя параметра шаблона всегда CharT. Если это не так, добавьте еще один параметр в макрос. HTH

+0

Это лучше, чем мое решение для получения литерала (я думаю), но я не уверен, действительно ли букваль нужен, или просто 'basic_string'. –