2012-01-16 21 views
1

私は他のコードで定義した一連のクラスの汎用ラッパークラスを作成しています。私は、C++で変数としてテンプレートパラメータを格納できるテンプレートクラスを記述する方法があるかどうかを判断しようとしています。ここで私は仕事を見たいものの一例である:C++は変数としてテンプレートパラメータを格納します

template < class C > class generic { 
    public: 
     C obj; // used for custom type processing 

     template < class T > T other; // <- changeable variable (or something) 

     template < class T > setOther() { // Function to change variable 
      // code to change variable type, or set type 
     } 

     void doSomethingWithOther() { 
      // do some processing for other, like call 
      // specific member function or something 
      (((other*)obj)->*SomeGenericMethod)() 
     } 
} 

int main(int argc, char **argv) { 
    Bar bObj; 
    generic<Foo> fObj; 
    fObj.setOther<Bar>(); 
    fObj.doSomethingWithOther(); 
    return 0; 
} 

私は上記のコードは、多くの理由のためにコンパイルされません知っているが、私の質問は、機能に関して、よりあります。後で型指定子として使用できる変数(または関数などを使用)としてテンプレートパラメータを格納できる方法はありますか?標準的な方法がない場合は、希望の結果につながる可能性のあるSOコミュニティのアイデアはありますか?

Boostや他のサードパーティのライブラリを使用しないでください。できるだけ "STL"(C99)にしてください。

私が持っていたもう一つのアイデアは、デフォルトの特殊化を使用していた:私たちが持っていたと仮定し

template < class C, class T = void* > class generic { 
    public: 
     C obj; 
     T other; 
     // ... more code 
} 

が、そのインスタンスで

、以下:

class Test1 { 
    public: 
     generic<Foo> *G1; 
     generic<Foo, Bar> *G2; 
}; 

私は後でにG1の種類を変更したい場合他の処理を行うと、次のようなことが言えます。

G1 = new generic<Foo, Bar>(); // compile error, different types 

ただし、テンプレートクラスTがデフォルトでvoid*に設定されていても、タイプがgeneric<C>で、タイプがgeneric< C, T >のG1が異なるタイプのため、コンパイルエラーが発生します。

申し訳ありませんが、私はこのコードで私の意図を可能な限り明確にしようとしています。また、上記の私の声明で私を修正してください。(長い日=私の脳活動が少ない)

この問題の助けを前もってお礼してください。

編集1:

明確にするために、otherデータメンバーは、私はクラス型を保持するために、そのメンバーを希望することを示すために、単にそこにあります。これは、コードに他のクラスのメンバがインスタンス化されたメンバ関数を呼び出すためです。別のクラスのメンバ関数を呼び出すと、コンパイルエラーが発生します。

残念ながら私たちの組み込みコンパイラは古く、0x機能セットをサポートしていないため、残念ながらC++ 0x機能を使用することはできません。さもなければそれは明らかな解決策になるでしょう。私は基本的にインスタンス化するクラスがthisポインタ

にメモリ空間とアクセスする必要があります自分自身とその呼ばれるメンバ関数内から他のインスタンス化のクラスのメンバーを呼び出すことができるように、システムのデリゲート型で構築することが午前

例:Delegateクラスの上記の例void operator()()

class Foo { 
    public: 
     Delegate other; 
} 

class Bar { 
    public: 
     void SomeFunction() { 
      std::cout << "hello from Bar::SomeFunction, data = " << data << std::endl; 
     } 

     int data; 
} 

int main() { 
    Foo F; 
    Bar B; 
    B.data = 10; 
    F.other = Delegate::attach<Bar>(&Bar::SomeFunction, &B); 
    // Delegate::attach is defined as 
    // template < class T > Delegate attach(void (T::*fnPtr)(void*), T *obj) 
    F.other(); 
} 

次いで(*fnPtr)()を介して、他のメンバ関数を呼び出します。この方法で呼び出された場合、関数はメンバーデータにアクセスすることができません(thisポインタの知識なし)。参照されたオブジェクト(すなわち、(*fnPtr)(obj))、関数はメンバーデータにアクセスできるようになりました。

私はDelegate otherが任意のメンバーにアタッチできるように前後にキャストできる汎用class typeオブジェクトを指定することでこれを解決しようとしています。

+0

? –

+6

¤「Boostや他の第三者図書館」は自滅しています。あなたは再びその車輪を再発明したくないので、boost :: anyまたはboost :: variantを使用してください(どちらが忘れているか)。そのソースコードを出発点として使用することはできますが、改善する可能性は低いです。改良を加えないと品質が低下するだけです。とにかく、なぜ地球上でこれをしたいのですか?それは本当にその問題について尋ねるのではなく、いくつかの問題に想像された解決策**を求めているように見えます。もしそうなら、問題について質問してください。 Chest&hth。 –

+1

"できるだけSTLを保つ"(私はあなたがC++標準ライブラリを意味すると仮定します):標準がBoostとその著者の影響を受けていることを知っていますか? – pmr

答えて

3

問題を解決しようとしていることは明らかではありません。あなたのコードでは、class Cの目的は何ですか?とにかく、あなたが望むものを推測します。仮想のinterfaceを持つ共通の基底クラスから派生し、genericクラスにそのinterfaceへのポインタを保持させる基本テンプレートクラスimplementationを使用します。 `それが何であるかを決定するために依存することother`う何

class generic { 
    class interface { 
    public: 
     virtual ~interface(){} 
     virtual void SomeGenericMethod()=0; 
    }; 
    template <class T> 
    class implementation: public interface { 
     T data; 
    public: 
     implementation(const T& d) :data(d) {} 
     virtual void SomeGenericMethod() 
     {return data.SomeGenericMethod();} 
    }; 
    public: 
     std::unique_ptr<interface> data; 

     template < class T > void setOther(const T& other) { 
      data.reset(new implementation<T>(other)); 
     } 

     void doSomethingWithOther() { 
      data->SomeGenericMethod(); 
     } 
}; 

int main(int argc, char **argv) { 
    generic fObj; 
    Bar bObj; 
    fObj.setOther(bObj); 
    fObj.doSomethingWithOther(); 
    return 0; 
} 

​​

+0

こんにちは、 'クラスC'は、私が今使っているコードで持っている署名の一部です。一般クラスの他の部分で使われています。問題の結果にはあまり重要ではありません。とにかく、返信とヒントをありがとう、私はあなたが正しい軌道に私を得るかもしれないと思うので、あなたの提案のバリエーションを試してみます – txtechhelp

+0

良いニュースは、私は今C++ 0xと仮想インターフェイストリックは私がやろうとしていたことの目標達成に終わった...ありがとう! – txtechhelp

+0

@txtechhelp:うれしい! 'unique_ptr'は答えの鍵ではなく、間違いを防ぐだけです。 –

0

コンパイル時に正確な型がわからない場合、それをテンプレートパラメータとしてエンコードすることはできません。それらはコンパイル時に知られていなければならず、その後変更することはできません。あなたに役立つ例として、Boost.Any(任意の可能な種類)またはBoost.Variant(複数の既知の種類)をチェックしてください。 anyは妥当な努力を払って実装することができますが、variantほどです。 C++テンプレートに関する知識があれば、コードを実際に理解していなくても実装しようとするべきではないでしょう。

+0

情報をいただき、ありがとうございます。私はBoostライブラリがそのバリ​​アント型をどのように実装しているかを見て、それらが助けになるかどうかを見ていきます。残念なことに、厳格なコード化の施行のために、私は第三者図書館を持ち込むことはできません。そうでなければ、これはすべて虚偽のことです。 – txtechhelp

+0

しかし、あなた自身で実装しようとしないでください。 – pmr

0

あなたの主な目標は、otherのメンバー機能を呼び出すことです。

この場合、otherは必要ありませんが、コールをカプセル化するファンクタだけです。例えば。 C++ 11またはTR1:

template <class C> struct A { 
    C obj; 
    std::function<void()> op; 
    void f() { 
     // ... 
     op(); 
    } 
}; 

struct B { 
    void g() { std::cout << "moo" << std::endl; } 
}; 

int main() { 
    A<int> a; 
    B b; 
    a.op = std::bind(&B::g, &b); 
    a.f(); 
} 
+0

こんにちはゲオルグ、情報のおかげで、残念ながら私は現在の状況(コンパイラのサポートなし)に役立つ任意のC + +の0x機能を使用することはできません。私はそのシンプルさのためにアイデアが好きですが、私は本質的に私のコードでこの機能をエミュレートして、Googleに戻したいと考えています。 – txtechhelp

+0

@txt:[ファーストデリゲート](http://www.codeproject.com/ KB/cpp/FastDelegate.aspx)、または[boost :: function]と[boost :: bind'だけを[bcp](http://www.boost。org/doc/libs/1_48_0/tools/bcp/doc/html/index.html)? –

関連する問題