У меня есть шаблон класса, скажем:
template<class T>
class someClient
{
void someCallbackA() {foo_->onA();}
void someCallbackB() {foo_->onB();}
private:
T* foo_;
};
который я могу создать с кучей разных типов T, которые поддерживают onA
а также onB
интерфейс. У меня случается случай, когда два из нескольких разных типов T
Я использую нуждается в особом поведении, контролируемом someClient
поэтому мне нужно добавить некоторую функцию doBar()
к этим двум типам (назовите их Edge1
а также Edge2
). Тогда я хочу часть someClient
код для вызова foo_->doBar()
но без разрыва, когда тип foo_
не имеет этого Есть ли способ использовать boost::enable_if
иметь someClient::doBar()
который позвонит foo_->doBar()
только для этих двух типов, но не быть там или расширяться до нуля, если типы не Edge1
или же Edge2
?
Я думал так:
template <class T, enable_if<mpl_or<is_same<T,Edge1>, is_same<T,Edge2> > >
someClient<T>::doBar() {foo_->doBar();}
Я думаю, что это делает то, что вы хотите. Я использовал C ++ 11 <type_traits>
вместо буста:
struct Edge {
void doBar() { std::cout << "did Bar."; }
};
template<typename T>
class someClient
{
public:
template<typename U = T>
typename
std::enable_if<std::is_same<U, Edge>::value, void>::type
doBar() { foo_->doBar(); }
template<typename U = T>
void doBar( typename std::enable_if<!std::is_same<U, Edge>::value, void>::type* = 0 )
{ /* do nothing */ }private:
T* foo_;
};
int main()
{
someClient<int> i;
someClient<Edge> e;
i.doBar();
e.doBar(); // outputs "did Bar."}
doBar()
Для этого должен быть сам шаблон, объяснение здесь: std :: enable_if для условной компиляции функции-члена
Вам не нужно тянуть какие-либо специальные трюки на всех, если вы просто не делаете вызов функции-члены, которые не имеют смысла. Функции-члены шаблона специализируются только при необходимости (если вы не добавите явную специализацию). Так что следующий код работает нормально:
template <typename T> struct Foo
{
void do_foo() { p->foo(); }
void do_bar() { p->bar(); }
T * p;
};
struct A { void foo() {} };
int main()
{
A a;
Foo<A> x = { &a };
x.do_foo();
}
Дело в том, что Foo<A>::do_bar
не будет компилироваться, это не проблема, так как функция-член никогда не создается. А также p->bar
не ошибка компилятора, потому что p
имеет зависимый тип, и строка, таким образом, анализируется только во второй фазе поиска (что никогда не происходит).