1

私はテンプレートクラスを持っています:

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

private:
T* foo_;
};

onAandonBインターフェイスをサポートするさまざまな型 T の束でインスタンス化できます。私が使用するいくつかの異なるタイプのうちの 2 つがT特定の動作を制御する必要がある場合があるため、これら 2 つのタイプにsomeClient関数を追加する必要があります (それらを および と呼びます)。次に、コードの一部を呼び出す必要がありますが、型にそれがない場合でも中断することはありません。これらの2つのタイプのみを呼び出すが、そこには存在しない、またはタイプがまたはでない場合は何も展開しないようにする方法はありますか?doBar()Edge1Edge2someClientfoo_->doBar()foo_boost::enable_ifsomeClient::doBar()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メンバー関数はインスタンス化されないため、コンパイルされないという事実は問題ではありません。依存型があり、行は2番目のルックアップフェーズでのみ解析されるため(これは決して起こりません) 、p->barコンパイラエラーではありません。p

于 2012-09-04T22:43:01.833 に答える
1

これはあなたが望むことだと思います。<type_traits>ブーストの代わりにC++11 を使用しました。

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 に答える