2016-08-05 7 views
0

私はABの2種類のクラスを持っています。これはOperatorクラスのサブクラスで、operate()メソッドを持っています。継承またはテンプレートを使用した特別なケースの振る舞い

class Operator { 
    // ... 
    virtual void operate() = 0; 
}; 
class A : public Operator { 
    void operate() { /* ... */ } 
}; 
class B : public Operator { 
    void operate() { /* ... */ } 
}; 

私は2つの操作を実行するクラスを作成したいのですが、両方の操作がタイプBであるときに独特の振る舞いを持っています。何かのように

class DoubleOperator { 
    Operator* operator1; 
    Operator* operator2; 
    // ... 

public: 
    void operateTwice() { 
     if (/* operator1 and operator2 are of type B */) { 
      // Do a special combined operation. 
     } else { // Otherwise, do the operations separately. 
      operator1->operate(); 
      operator2->operate(); 
     } 
    } 
}; 

この動作を生成するために継承またはテンプレートを使用する簡単な方法はありますか?

+0

をおそらく 'DoubleOperator'は' Operator'オブジェクトへのポインタまたは参照を持っている - それができます抽象型のメンバーを持っています。 – aschepler

+0

そうです。私はそれを更新します。 – ech

+1

[double dispatch](https://en.wikipedia.org/wiki/Double_dispatch)が必要なのでしょうか? – kfsone

答えて

0

あなたが求めているWharは次のとおりです。

Derived静的な型Base& と変数の動的型であるかどうかを確認する方法は?

struct Base 
{ 
    virtual void f(){} 
}; 
struct Derived:Base{}; 

Derived d; 
Base& b = d; 

if (typeid(b)==typeid(Derived)) 
{ 
    //... 
} 

説明:

5.2.8/2は言う:

型IDは、そのタイプ多型クラス型(10.3)、その結果であるglvalue式に適用する場合gl値が参照する最も派生したオブジェクト(1.8)のタイプを表すstd :: type_infoオブジェクト(ダイナミック タイプ)に を参照しますs。 [...]。

だから、我々はそれにvirtual機能を追加することにより、Baseポリモーフィッククラス型を作り、我々はその後、動的な型を返さtypeidを適用しました。

1

タイプ消去中間関数を持つ演算子とビットを使用すると、SFINAEが得られます。
それは最小限、実施例(C++ 11に簡単に変換できるC++ 14、)次の:あなたが拡張することができます/あなたのニーズに応じてprotoを変更

#include<type_traits> 
#include<iostream> 

class Operator { 
    // ... 
    virtual void operate() = 0; 
}; 
class A : public Operator { 
    void operate() { /* ... */ } 
}; 
class B : public Operator { 
    void operate() { /* ... */ } 
}; 

class DoubleOperator { 
    template<typename T, typename U> 
    static 
    std::enable_if_t<std::is_same<T,U>::value> 
    proto() { 
     std::cout << "same" << std::endl; 
     // Do a special combined operation. 
    } 

    template<typename T, typename U> 
    static 
    std::enable_if_t<not std::is_same<T,U>::value> 
    proto() { 
     std::cout << "not same" << std::endl; 
     // Otherwise, do the operations separately. 
    } 

    Operator* operator1; 
    Operator* operator2; 
    void(*internalOperatorTwice)(void); 
    // ... 

public: 
    template<typename T, typename U> 
    DoubleOperator(T *t, U *u): operator1{t}, operator2{u} { 
     internalOperatorTwice = &proto<T, U>; 
    } 

    void operateTwice() { 
     internalOperatorTwice(); 
    } 
}; 

int main() { 
    A a1; 
    A a2; 
    B b; 
    DoubleOperator do1{&a1, &a2}; 
    do1.operateTwice(); 
    DoubleOperator do2{&a1, &b}; 
    do2.operateTwice(); 
} 

を。

EDIT

私はもう一度質問を読んで、ここでの回答の洗練されてきました。
私が上記のことはまだ有効です。あなたは異なる何かをしたい場合は、Bの2つのインスタンスを持っている場合とにかく、唯一、次のprotoの機能を使用することができます。

template<typename T, typename U> 
static 
std::enable_if_t<std::is_same<T,B>::value and std::is_same<U,B>::value> 
proto() { 
    std::cout << "same" << std::endl; 
    // Do a special combined operation. 
} 

template<typename T, typename U> 
static 
std::enable_if_t<not (std::is_same<T,B>::value and std::is_same<U,B>::value)> 
proto() { 
    std::cout << "not same" << std::endl; 
    // Otherwise, do the operations separately. 
} 
+0

TとUが両方とも特定の型であるかどうかをチェックするためにこれを修正する方法はありますか? – ech

+0

@ech答えを更新しました。今それは質問に正確に答えます。 – skypjack

+0

さて、ダウンボッターのコメントは答えを最適化するのに役立ちます...ありがとうございます。 – skypjack

関連する問題