web-dev-qa-db-ja.com

std :: unique_ptr <Derived>をstd :: unique_ptr <Base>に変換する

C++ 11を使用して、基本クラスと派生クラスを処理するファクトリ関数があるとします。

_#include <memory>

using namespace std;

struct B { virtual ~B() {} };
struct D : B {};

unique_ptr<B> MakeB()
{
    auto b = unique_ptr<B>( new B() );
    return b; // Ok!
}

unique_ptr<B> MakeD()
{
    auto d = unique_ptr<D>( new D() );
    return d; // Doh!
}
_

上記の最後の行では、move(d)が順番に必要です 機能させるために 、それ以外の場合は I get "エラー:_std::unique_ptr<D>_からの無効な変換_std::unique_ptr<D>&&_へ」私の直感は、このコンテキストでは、コンパイラーは暗黙的にdを右辺値にしてベースポインターに移動できることを知っているはずですが、そうではないということです。

これは私のコンパイラ(gcc 4.8.1およびVS2012)での不適合ですか? _unique_ptr_の意図された設計?標準の欠陥?


Update:C++ 14で修正されました。 GCC 9などの新しいコンパイラ 元のコードを受け入れる _-std=c++11_を使用しても。

42
metal

コンパイラの動作は正しいです。タイプが同じである場合、暗黙的な移動のみが存在します。暗黙的な移動は、コンパイラーが実際に許可されている場合にコピーの省略を実行できないという点で指定されているためです(12.8/31および12.8/32を参照)。

12.8/31(コピーの省略):

クラスの戻り値の型を持つ関数のreturnステートメントで、式が非揮発性の自動オブジェクトの名前である場合(関数またはcatch-clauseパラメーターを除く)同じcv-非修飾型関数の戻り値の型 ...

12.8/32(暗黙の移動):

コピー操作の除外の基準[...]が満たされると、コピーのコンストラクターを選択するためのオーバーロード解決が最初に実行されますオブジェクトが右辺値で指定されているかのように

34
Simple