2009-07-28 6 views
3

テンプレートを使った私の冒険では、Containerクラスに保持されているItemTypeだけでなく、アイテムをどのように並べるべきかを決定するFunctorの引数にテンプレートを貼り付けました。ここまでは順調ですね。同じクラステンプレートの異なるインスタンス化のプライベート部分にアクセスする方法はありますか?

1つのコンテナの内容を別のコンテナにコピーしたいときに発生した小さな問題:2つのコンテナに異なるFunctorタイプがある場合、技術的には関連のないクラスです。したがって、コンテナAはコンテナBの非公開のコンテンツにアクセスすることはできません。私がアクセスする必要があるすべてのものを作る以外に、この問題に対処する良い方法はありますか?おそらく、 "友人"宣言をテンプレートするための何らかの方法はありますか?問題を実証する

例のコードは、次のとおりです。

#include <stdio.h> 

class FunctorA {}; 
class FunctorB {}; 

template <class ItemType, class Functor> class MyContainer 
{ 
public: 
    MyContainer() : _metaData(0) {/* empty */} 

    template<class RHSFunctor> void CopyFrom(const MyContainer<ItemType, RHSFunctor> & copyFrom) 
    { 
     _metaData = copyFrom._metaData; 
     _item  = copyFrom._item; 
    } 

private: 
    int _metaData; 
    ItemType _item; 
}; 

int main(int argc, char ** argv) 
{ 
    MyContainer<void *, FunctorA> containerA; 
    MyContainer<void *, FunctorB> containerB; 

    containerA.CopyFrom(containerB); // error, containerA::CopyFrom() can't access containerB's private data! 
    return 0; 
} 
+0

は、クラスをインスタンス化することができないことを反映するためにタイトルを明確化していますが、クラステンプレートをインスタンス化することができます。混乱の一部は、クラステンプレートが型自体ではなく、各インスタンス化が別の型であるという事実に従います。 – MSalters

答えて

2

あなたは、本格的な2引数は、そのベースをサブクラス化テンプレート持って、ちょうどitemTypeに上のテンプレートベーステンプレートクラスを作るそこにデータを保持することができ、とにかくファンクタに依存しないので、コピー元をベースクラスに入れてください。あなたが指摘するようにすなわち:

template <class ItemType> class MyContainerBase 
{ 
public: 
    MyContainerBase() : _metaData(0) {/* empty */} 

    void CopyFrom(const MyContainerBase<ItemType> & copyFrom) 
    { 
     _metaData = copyFrom._metaData; 
     _item  = copyFrom._item; 
    } 

protected: 
    int _metaData; 
    ItemType _item; 
}; 

template <class ItemType, class Functor> class MyContainer: 
    public MyContainerBase<ItemType> 
{ 
    // whatever you need here -- I made the data above protected 
    // just on the assumption you may need to access it here;-) 
}; 
+0

Jeremy、このテクニックは、より少数のテンプレート引数(時にはnone)を持つ基本クラスに多くの振る舞いを入れて、サブクラスに特定の特別な機能を追加することは非常に一般的なテクニックであり、多く使われています。 (GNU libstdC++には、調べる価値のある多くのケースがあります。) – quark

+0

これはまさに私が探していたものです。ありがとう! –

1

、あなたはまた、フレンド関数を使用することができます。

class FunctorA {}; 
class FunctorB {}; 

template <class ItemType, class Functor> class MyContainer 
{ 
public: 
    MyContainer() : _metaData(0) {/* empty */} 

    template<class CmnItemType, class LHSFunctor, class RHSFunctor> 
    friend void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom 
    , MyContainer<CmnItemType, RHSFunctor> & copyTo); 

private: 
    int _metaData; 
    ItemType _item; 
}; 

template<class CmnItemType, class LHSFunctor, class RHSFunctor> 
void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom 
    , MyContainer<CmnItemType, RHSFunctor> & copyTo) 
{ 
    copyTo._metaData = copyFrom._metaData; 
    copyTo._item  = copyFrom._item; 
} 


int main(int argc, char ** argv) 
{ 
    MyContainer<void *, FunctorA> containerA; 
    MyContainer<void *, FunctorB> containerB; 

    Copy(containerB, containerA); 
    return 0; 
} 
+0

それはまた良いアイデアです、ありがとう! –