Требовать, чтобы возвращаемый тип шаблона функции был специализацией шаблона - PullRequest
1 голос
/ 17 сентября 2010

Я какое-то время разбирался со stackoverflow, но либо я недостаточно разбираюсь в шаблонах, чтобы найти решение, либо на него просто не было ответа раньше.

В этом примере:

template <typename T> T f();

Можно ли заставить функцию требовать, чтобы тип T был специализацией шаблона std::basic_string?

Я мог бы иметь шаблон, определенный с T как тип std::basic_stringтак же (используя std::basic_string<T> внутренне, конечно):

template <typename T> std::basic_string<T> f();

Но тогда я не смог бы передать std::string или std::wstring в функцию (ожидая, что возвращаемый тип будет std::string и std::wstring, соответственно), что является настоящей целью (чтобы можно было передавать любой тип, производный от шаблона std::basic_string).

Ответы [ 3 ]

8 голосов
/ 17 сентября 2010

Частичная специализация позволяет вам проверить, является ли тип специализацией определенного шаблона.SFINAE - это трюк, который может «отключить» объявление шаблона функции.Решение объединяет эти методы.

template< typename T > // by default,
struct enable_if_basic_string {}; // a type is not a basic_string

template< typename CharT, typename Traits >
struct enable_if_basic_string< basic_string< CharT, Traits > > {
    typedef basic_string< CharT, Traits > type; // same as argument type
};

// enable_if_basic_string<>::type exists only if T specializes basic_string
// if not, compiler ignores function declaration per SFINAE.
template< typename T >
typename enable_if_basic_string< T >::type
F() {
    .....
}

Если вы имеете в виду деривацию, а также специализацию, вы также можете взглянуть на std::tr1::is_convertible и enable_if.

5 голосов
/ 17 сентября 2010

Вместо того, чтобы требовать, чтобы T была специализацией std::basic_string, почему бы просто не предположить , что T является специализацией std::basic_string, и позволить экземпляру шаблона не работать, если это не так. Просто используйте вещи из std::basic_string, которые вам нужны.

Например,

template <typename T>
T get_first_three_chars(const T& str) { return str.substr(0, 3); }

Здесь мы предполагаем, что T имеет функцию-член substr; если этого не произойдет, создание экземпляра завершится неудачно, что приведет к ошибке компиляции.

1 голос
/ 17 сентября 2010

Это невозможно в vanilla C ++. Для C ++ 0x была предложена языковая конструкция, которая позволила бы это сделать, к сожалению, она была отброшена.

Вы можете сделать это в определенной степени с помощью библиотеки проверки концепции Boost, однако: http://www.boost.org/doc/libs/1_44_0/libs/concept_check/concept_check.htm

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...