Извините, что ввел вас в заблуждение в последнем ответе, я на мгновение подумал, что это будет проще. Поэтому я постараюсь предоставить полное решение здесь. Общий подход к решению этого типа проблем состоит в том, чтобы написать вспомогательный шаблон traits и использовать его вместе с enable_if
(либо C++11, либо ручная реализация), чтобы выбрать специализацию класса:
Черта
Простой подход, не обязательно лучший, но простой для написания:
template <typename T>
struct has_nested_Vec {
typedef char yes;
typedef char (&no)[2];
template <typename U>
static yes test( typename U::Vec* p );
template <typename U>
static no test( ... );
static const bool value = sizeof( test<T>(0) ) == sizeof(yes);
};
Подход прост, предоставьте две шаблонные функции, которые возвращают типы разных размеров. Один из них принимает вложенный тип Vec
, а другой — многоточие. Для всех тех типов, которые имеют вложенный Vec
, первая перегрузка является лучшим соответствием (многоточие является худшим соответствием для любого типа). Для тех типов, которые не имеют вложенного Vec
SFINAE, эта перегрузка будет отброшена, и единственным оставшимся вариантом будет многоточие. Итак, теперь у нас есть трейт, который спрашивает, есть ли у какого-либо типа вложенный тип Vec
.
Включить, если
Вы можете использовать это из любой библиотеки, или вы можете накатить свою собственную, это довольно просто:
template <bool state, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true,T> {
typedef T type;
};
Когда первым аргументом является false
, единственным вариантом является базовый шаблон, который не имеет вложенного type
, если условие равно true
, то enable_if
имеет вложенный type
, который мы можем использовать с SFINAE.
Реализация
Теперь нам нужно предоставить шаблон и специализацию, которая будет использовать SFINAE только для тех типов с вложенным Vec
:
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename enable_if<has_nested_Vec<T>::value>::type > {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
Всякий раз, когда мы создаем экземпляр Functor
с типом, компилятор попытается использовать специализацию, которая, в свою очередь, создаст экземпляр has_nested_Vec
и получит истинное значение, переданное в enable_if
. Для тех типов, для которых значение равно false
, enable_if
не имеет вложенного типа type
, поэтому специализация будет отброшена в SFINAE и будет использоваться базовый шаблон.
Ваш конкретный случай
В вашем конкретном случае, когда кажется, что вам действительно не нужно специализировать весь тип, а только оператор, вы можете смешать три элемента в один: Functor
, который отправляет одну из двух внутренних шаблонных функций на основе наличие Vec
, устраняя необходимость в enable_if
и классе признаков:
template <typename T>
class Functor {
template <typename U>
void op_impl( typename U::Vec* p ) const {
std::cout << "specialized";
}
template <typename U>
void op_impl( ... ) const {
std::cout << "general";
}
public:
void operator()() const {
op_impl<T>(0);
}
};
person
David Rodríguez - dribeas
schedule
04.07.2012
compiler
, он обычно используется для вопроса о самом процессе компиляции, тогда как этот вопрос касается языка C++. - person Matthieu M.   schedule 08.07.2012