2015-07-18 2 views
1

Я хотел бы написать функцию, которая будет выглядеть примерно так:строковый литерал - преобразование шаблона между типами полукокса

template <typename CharT> 
std::basic_string<CharT> convert(char const *); 

и использоваться следующим образом:

convert<char>("Hello World!");  // "Hello World!" 
convert<wchar_t>("Hello World!"); // L"Hello World!" 
convert<char16_t>("Hello World!"); // u"Hello World!" 
convert<char32_t>("Hello World!"); // U"Hello World!" 

я мог бы использовать std::codecvt и Ко, но я считаю это почти бессмысленным, так как было бы проще использовать макрос, который добавляет L, u или U с 0 стоимостью.

К сожалению, шаблоны и макросы не действуют на одном уровне ... Итак, вот мой вопрос: будет ли какой-то способ mix им? Или есть лучший способ?

Моя основная цель - избежать повторения (специализации) кода: некоторые функции, которые я кодирую, - это CharT шаблоны и использовать строковые литералы, и это будет единственной разницей. В качестве примера:

template <typename CharT> 
void foo (std::vector<std::basic_string<CharT>> const & vec, 
      std::basic_string<CharT> str = convert<CharT>("default")); 

Это позволит избежать специализации foo() для каждого типа символов.

Большое спасибо за вашу помощь

+1

Я не вижу необходимости в специализации здесь, просто используйте, например. 'codecvt' с' char' в качестве типа «источник» и 'CharT' как тип« destination »? –

+0

Действительно, я уже думал об этом позже. Отредактировано, спасибо. –

+0

@JoachimPileborg Да, но это все еще расчет времени исполнения. OP хочет избежать этого, поскольку они являются строковыми литералами, и добавление определенного префикса будет делать трюк. – edmz

ответ

0

Наконец-то я получил идею использования макросов для генерации каждые 4 перегрузки функции foo.

template <typename CharT> 
void foo (std::vector<std::basic_string<CharT>> const & vec, 
      std::basic_string<CharT> str = convert<CharT>("default")); 

становится

#define FOO(CharT, prefix) \ 
void foo (std::vector<std::basic_string<CharT>> const & vec, \ 
      std::basic_string<CharT> str = prefix ## "default"); 

и я просто добавить

FOO(char,) 
FOO(wchar_t, L) 
FOO(char16_t, u) 
FOO(char32_t, U) 

четыре строки, которые я также могу поставить в другой макрос GENERATE, так что я могу просто позвонить

GENERATE(FOO) 

Я знаю макросы ... но я добрался до своего главная цель избежать повторения кода. :-)

Спасибо всем за помощь!

0

Edited: Это будет работать с C++11. Поскольку оператор не может быть шаблоном, вы можете изменить перегрузку оператора на функцию convert.

#include <string> 

std::basic_string<char> operator ""_s(const char * str, std::size_t len) { 
    return std::basic_string<char> (str, str + len); 
} 

std::basic_string<char16_t> operator ""_u(const char * str, std::size_t len) { 
    return std::basic_string<char16_t> (str, str + len); 
} 

std::basic_string<char32_t> operator ""_U(const char * str, std::size_t len) { 
    return std::basic_string<char32_t> (str, str + len); 
} 

std::basic_string<wchar_t> operator ""_L(const char * str, std::size_t len) { 
    return std::basic_string<wchar_t> (str, str + len); 
} 


int main() { 
    std::string s1 = "Hello World!"_s; 
    std::u16string s2 = "Hello World!"_u; 
    std::u32string s3 = "Hello World!"_U; 
    std::wstring s4 = "Hello World!"_L; 
    return 0; 
} 

См LIVE DEMO работу.

+0

Спасибо за ваш ответ, но я боюсь, что вам нужно будет префикс литералов 'L',' u' или 'U' (именно этого я хочу избежать). Здесь вы генерируете только std :: basic_string s. –

+0

@JemCpp Мне не нужно ничего префикса, только суффикс 's' или' _s'. – Shreevardhan

+0

Взгляните на [этот идеон] (https://ideone.com/4Q1ptE) и [документация] (http://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s): параметрами являются 'char',' wchar_t', 'char16_t' и' char32_t', а не только 'char'. –