1

我有一个模板类,说:

template<class T>
class someClient
{
void someCallbackA() {foo_->onA();}
void someCallbackB() {foo_->onB();}

private:
T* foo_;
};

我可以用一堆支持onAandonB接口的不同类型 T 来实例化它。我碰巧有一种情况,T我使用的几种不同类型中的两种需要控制一个特定的行为,someClient所以我需要doBar()为这两种类型添加一些功能(调用它们Edge1Edge2)。someClient然后我想要调用一部分代码,foo_->doBar()但当类型没有时不会中断foo_。有没有一种方法可以boost::enable_if让 a someClient::doBar()which 只调用这两种类型,但不存在,或者foo_->doBar()如果类型不存在,则扩展为空?Edge1Edge2

我的思路是:

template <class T, enable_if<mpl_or<is_same<T,Edge1>, is_same<T,Edge2> > >
someClient<T>::doBar() {foo_->doBar();}
4

2 回答 2

3

如果您只是不调用没有意义的成员函数,则根本不需要任何特殊技巧。模板成员函数仅在需要时才被特化(除非您添加显式特化)。所以下面的代码工作正常:

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具有依赖类型,因此仅在第二个查找阶段(永远不会发生)解析该行。

于 2012-09-04T22:43:01.833 回答
1

我认为这可以满足您的要求。我使用 C++11<type_traits>而不是 boost:

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 有条件地编译成员函数

于 2012-09-04T23:16:39.743 回答