2016-09-28 5 views
6

Предположим, что у меня есть пользовательский строковый класс:Выберите шаблон строки неявно пропусканием константный символ *

class my_string : public std::string 
{ 
    // ... 
} 

И я хочу сделать шаблонный функцию, которая принимает и с my_string по умолчанию:

template <typename TString = my_string> 
TString do_something(const TString& input) 
{ 
    // ... 
} 

Но когда я называю его:

auto result = do_something("abcdef"); 

Он называет (конечно) do_something<char[7]>(). Как заставить это позвонить do_something<my_string>без, явно указывая тип (т. Е. Напишите do_something("abcdef"), а не do_something<my_string>("abcdef"))?

+1

Примечание: хотя это всего лишь пример, никогда не выводятся из std :: string! –

+6

Я бы просто добавил перегрузку для 'const char []' и перешел к функции, которую вы хотите вызвать. – NathanOliver

+1

Буквенный суффикс строки может помочь в качестве альтернативы: '' abcdef 's' и 'operator'" _my_s' '" abcdef "_my_s'. – Jarod42

ответ

3

Уточнить для "construct from string arguments".

template <typename TString = my_string, 
typename std::enable_if<std::is_base_of<std::string, TString>::value>::type = nullptr> 
TString do_something(const TString& input) 
{ 
    // ... 
} 

template <typename ...Args, 
typename std::enable_if<std::is_constructible<my_string, Args....>::value>::type = nullptr> 
my_string do_something(Args&&... args) 
{ 
    return do_something<my_string>({args}); 
} 
1

Действительно ли вам нужен шаблон функции? Простая функция:

my_string do_something(my_string const& input) { ... } 

решает использовать ваш случай использования. Вы можете передать my_string или строковый литерал, или даже braced-init-list, и все просто работает.


Поскольку вам нужен шаблон по другим причинам, вы можете просто обеспечить перегрузку для массивов const char:

template <class TString> 
TString do_something(TString const&) { ... } 

template <size_t N> 
my_string do_something(const char (&arr)[N]) { 
    return do_something(my_string{arr, N-1}); 
} 

Примечание: нет никаких причин, чтобы обеспечить по умолчанию для параметра шаблона TString. Нет смысла использовать это значение по умолчанию.

+1

Он возвращает 'my_string', который мне не нужен в старом коде, который использует' std :: string'. – vladon

+0

Вы действительно хотите взять массив по ссылке здесь? Я бы подумал, что параметр 'const char []' будет более полезен, поскольку вы можете передать массив или указатель. – NathanOliver

+0

@NathanOliver Я бы предпочел просто захватить строковые литералы. – Barry

1

Re

Я хочу сделать шаблонную функцию, которая принимает как с my_string по умолчанию

#include <string> 

template< class Type > 
struct Explicit_t_ { using T = Type; }; 

template< class Type > 
using Explicit_ = typename Explicit_t_<Type>::T; 

namespace my { 
    struct String: std::string { using std::string::string; }; 
} // namespace my 

template< class Some_string > 
auto do_something(Explicit_<Some_string> const&) 
    -> Some_string 
{ return "Template func!"; } 

auto do_something(my::String const&) 
    -> my::String 
{ return "my::String!"; } 

#include <iostream> 
using namespace std; 
auto main() 
    -> int 
{ 
    cout << do_something("") << endl;  // Output "my::String!" 
    cout << do_something<std::string>("") << endl; 
} 

Вы можете позволить перегрузку my::String только вперед шаблон функции , если вы не хотите более специализированной или другой реализации.

Смежные вопросы