2012-01-26 6 views
0

非const参照がラッパーテンプレートのコピーコンストラクターのconst参照に変換されるようにするにはどうすればよいですか?私のコピーコンストラクタは論理的な移動コンストラクタ(pre-C++ 11より前)であることに注意してください。initのメンバーは現在どのラッパーが有効かを追跡します。非constがラッパーテンプレートのconstに変換できるようにする

template<typename T> 
class wrap 
{ 
    T & object; 
    bool init; 
public: 
    wrap(T& object) : object(object), init(true) { } 

    //attempt which fails since "init" is private in other type 
    template<typename O> 
    wrap(wrap<O> const & o) 
     : object(o.object) 
     , init(true) 
    { 
     const_cast<wrap<O>&>(o).init = false; 
    } 
}; 

その後、アクセスルールは、プライベートinit変数へのアクセスを許可するので、他のタイプは、まったく同じである場合、これは正常に動作します。基本的には、次のように動作するはずです:

//adding const 
wrap<Type> a(get()); 
wrap<Type const> b = a; 

//base type would also be nice 
wrap<BaseType> c = a; 
+0

"他のタイプがまったく同じ場合、実際にはそうではありません。それはテンプレートではなく暗黙のコピーコンストラクタを使用するので、両方とも 'init' setで終わるでしょう。 –

答えて

1

仲良くなる他の専門分野:

template <typename U> friend class wrap; 

以上のカプセル化のために、ちょうど彼らの変換コンストラクタ:

template <typename U> template <typename O> 
friend wrap<U>::wrap(wrap<O> const &); 

それは良いだろうinitmutableを宣言すること; const_castを使用すると、誰かがconstオブジェクトをコピーしようとすると、未定義の動作が発生する危険性があります。

また、コンストラクタテンプレートは、が暗黙的に生成されたコピーコンストラクタにオーバーロードされないことに注意してください。またinitで正しいことを行うためにコピーコンストラクタが必要になります:

wrap(wrap const & o) : object(o.object), init(true) {o.init = false;} 
+0

これはうまくいきますが、 2番目のe?なぜ2つのテンプレート部品が必要ですか? –

+0

@ edA-qamort-ora-y:これは、クラステンプレート内の関数テンプレートを参照しているためです。それぞれに1つの 'template'が必要です。 –

0

まあアクセス制限を回避するためにあなたは、単に友人としてwrapの他のインスタンスを追加することができ、これの身体のどこかにtemplate<typename U> friend class wrap;を追加しますクラス。あなたの例をコンパイルする必要があります。

しかし、あなたは本当にそのようなコンパイラに嘘をつくべきではありません。 oconst refとすれば、それを変更せずにそれを変更しないと約束します。これは良い(または標準で許可されている)わけではないので、コンパイラはあらゆる方法でコードを壊すことがあります。非constとして引数を取る関数を呼び出すには、実際にはconst_castを使うべきですが、引数自体は変更されません。この場合、コンストラクタをtemplate<typename O> wrap(wrap<O>& o)と宣言することをお勧めします。あなたが本当にconst参照としてそれを取るしたい場合はまた、オブジェクトはまた、あなたはコピーコンストラクタを宣言されていないことに注意すべきであるconst

場合でも変更することができることを意味、mutableとして宣言initのルートを行くことができます(たとえtemplate<typename O> wrap(wrap<O> const & o)が受け入れることができるとしても、wrap<T>を受け入れることができるので、それも定義する必要があります。または、同じタイプにコピーすると、コンストラクタによって生成されたコピーコンストラクタが使用されます。

+0

コピーコンストラクタのデフォルトについての良い点。 –

関連する問題