12

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)...
{}

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

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コピー/移動コンストラクターが のコピー/移動コンストラクターを呼び出してcommon_workおり、別の種類の から変換する他のコンストラクター [コードには表示されていません] によって転送コンストラクターが使用されていたため、これは問題ありませんでしworkた。

work1その後、EBO などのcommon_work理由でを継承しようと考えました。新しいwork1クラスは次のようになりました

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

しかしwork1work_likeクラスであるため、突然転送コンストラクターがより適切に一致common_workするstatic_castようになりました。

ノート :

  • Scott Meyersによって与えられた同様の種類の例があり、コピー コンストラクターには const の追加が必要なため、コピー コンストラクターは転送コンストラクターをトリガーしますが、転送コンストラクターには何も必要ありません。しかし、この問題は間違ったクラス設計が原因で発生すると思いますが、ここでの問題は、暗黙的なコピー/移動中に基本クラスに渡される引数が完全に一致しないことが原因です。
  • 削除された関数もオーバーロード解決に参加し、正確に一致するとエラーが発生するため、ユニバーサル転送コンストラクター/割り当てを記述して暗黙的なものを削除することはできません。
  • 現在私が持っている解決策はcommon_work、 CRTP として作成することです。つまり、派生クラスの型をテンプレート引数として渡し、転送コンストラクターでそれを としてフィルター処理しenable_if<and_<work_like<T>,not_<is_same<T,Derived> > > >ます。work1そうしないと、基本クラスのコピー/移動コンストラクター/割り当てをstatic_cast明示的に手動で作成する必要があり、バグが発生しやすく、エラーが発生しやすく、メンテナンスが危険です。
4

1 に答える 1

1

この問題は、数年前に MSVC++ バグストラッカー ページで議論されました (したがって、まだ修正されていない場合は、MSVC++ の既知の問題です)。スタンダードは言う

  • ... ベースまたはメンバーは、x の対応するベースまたはメンバーで直接初期化されます。

バグレポートを読んだときにさまざまなコンパイラをテストしましたが、それらはすべて「魔法のようにキャスト」されていました。標準は非常に詳細(値のカテゴリとc / v修飾子についても)について静かに見え、「xの対応するベースで...」とだけ言っています。完全なオブジェクトを渡すのではなく、「x ではなく、対応するベース ... の x を使用」します (その方法でしか意味をなさないとさえ言えます)。

于 2013-07-18T19:21:11.840 に答える