12

私の理解では、根本的なC++暗黙コピーと移動コンストラクタの背後にある根拠? C++暗黙のコピーコンストラクタについて

T(T const& x) : 
    base1(x), base2(x) ... , 
    var1(x.var1), var2(x.var2)... 
{} 

移動コンストラクタに似て&移動アサインも同様のパターンを以下のコピー。

はなぜそれは次のような定義されていませんでしたか?

T(T const& x) : 
    base1(static_cast<base1 const&>(x)), 
    base2(static_cast<base2 const&>(x)) ... , 
    var1(x.var1), var2(x.var2)... 
{} 

Iは暗黙コピー/移動コンストラクタ/代入演算子、並びにいくつかの変換コンストラクタを持っていたクラスを有していました。私は仕事をいくつかの実装クラスに委任していました。

class common_work //common implementation of many work like classes 
{ 
    common_work(common_work const&) = default; 
    common_work(common_work&&) = default;// ... implicit constructors work for me. 
    //a forwarding constructor which can take many work like objects 
    template<class T, enable_if<work_like<T> > > 
    common_work(T&& x) { ... } 
}; 
class work1 //one of the implementation 
{ 
    work1(work1 const&) = default; 
    work1(work1&&) = default; ... 
    common_work impl_; 
}; 

work1コピー/移動コンストラクタはworkの別の種類に変換する[コードには示されていない] common_workためのコピー/移動のコンストラクタを呼び出す、およびコンストラクタは、他のコンストラクタによって使用された転送し、これは、微細でした。

次に、私はEBOとその他の理由でcommon_workからwork1を継承すると考えました。だから、新しいwork1クラスが

class work1 : private common_work 
{ 
    work1(work1 const&) = default; 
    work1(work1&&) = default; ... 
}; 

のように見えた。しかしとして、work1common_workためのコピー/移動コンストラクタがベースに派生からstatic_castを必要とするため、突然の転送コンストラクタは、より良い一致を得ていた、work_likeクラスです。

注:

  • コピー構造はコンストラクタを転送することは何を必要としないながらコピーコンストラクタは、CONST添加を必要とするコンストラクタを転送トリガScott Meyersによって与えられた例の同様の種類があります。しかし、私は、その問題は間違ったクラス設計のために発生すると考えていますが、ここでの問題は、暗黙のコピー/移動中に基本クラスに渡される引数が完全に一致しないためです。
  • 削除機能もオーバーロードの解決と原因エラーに参加しているため、正確に一致した場合、私は、ユニバーサル転送コンストラクタ/割り当てを書き、暗黙のものを削除することはできません。
  • 私は現在溶液は、テンプレート引数として渡さCRTP、すなわち派生クラスタイプとして、それはenable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >としてコンストラクタフィルタを転送にcommon_workを作ることです。それ以外の場合は、work1static_castのコピー/移動コンストラクタ/代入を、バグ、エラーが発生しやすく、メンテナンスの危険性を明示的に基底クラスに書き込む必要があります。
+0

おそらく、あなたは 'common_work'から派生した' T'を拒否するようにSFINAE制約を強化することでこれを回避できますか? –

+0

それは私が現在していることです。 NOTEセクションの3番目の点を見てください。しかし、 'is_same 'ではなく、 'is_same 、Derived> ' – abir

+0

、ごめんなさい。私は最後のノートを読んでいません:) –

答えて

1

この問題は、何年か前にMSVC++ bugstrackerページで議論されました(まだ修正されていない場合は、MSVC++の既知の問題です)。標準ベースまたはメンバーが直接初期化し、対応するベースまたはxのメンバーである...

  • 言います。

私はバグレポートを読んだとき、私は様々なコンパイラをテストしました、そしてそれらのすべてが「魔法のキャスト」。スタンダードは非常に細かいこと(値のカテゴリとc/vの修飾子についても)は静かであるように見えますが、「xの対応するベースで」と言うだけです。IMOは、 "xではなくxの対応する基底で..."というよりも、完全なオブジェクトを渡すよりも(私はそれがだけだと言っているだろう)その意味ではです。

+0

明示的にデフォルトされた特別なメンバー関数はまだMSVCに実装されていないことに注意してください(彼らは2013 RTMですぐにそれらを取得すると言いましたが)。 –

関連する問題