4

EDIT2:

明確にするために:

この質問は、実際にはデフォルト パラメーター自体とは何の関係もなく、コピー コンストラクターとムーブ コンストラクターとは何の関係もない問題から生じました。実際に質問に答える回答を受け入れました(質問のタイトルのためにここにいる場合は、それを読んでください)。最初にそれがうまくいかなかった理由を説明します。

なにが問題だったの?

したがって、「編集:」で説明されているように、問題は実際にはかなり単純です。

VisualStudio 2013 での will break コンパイルを含むクラスへの割り当てstd::vector<std::unique_ptr<T>>(他のバージョンではテストされていません) と、エラー メッセージは非常に不可解です。

コメントの前提は、VC コンパイラにバグがあり、存在しないコピー コンストラクタを呼び出そうとしたことです。

くそ、今何?

この仮定は実際には真実でしたが、私が最初に理解した意味ではそうではありませんでした.

実際、VCCMyClass実際には、暗黙的に定義するの移動コンストラクターを呼び出そうとします。しかし、ここに問題があり、正しく定義されていません。

move コンストラクターを明示的に定義する場合、MyClass(MyClass && a)次のようにコードを記述することで、実際にコンパイラーの動作を模倣できます。

MyClass(MyClass && a)
    : foos_(a.foos_)
{}

このコードを使用すると、暗黙的な定義を使用した場合とまったく同じエラー メッセージが生成されます。ここで何が問題なのかがすぐにわかると思います。このムーブ コンストラクターは実際に のコピー コンストラクターを呼び出そうとしますがfoos_、もちろん不可能です。明らかな理由でコピー コンストラクターを持たないstd::unique_ptr型であるため、その内容に対してコピー コンストラクターを呼び出すことはできません。

代わりにこのコードを使用すると、

MyClass(MyClass && a)
    : foos_(std::move(a.foos_))
{}

std::vectorの移動コンストラクターが呼び出され、そのコンテンツの移動コンストラクターが呼び出されるため、すべてが完全に正常に機能します。

それで、誰のせいですか?

可能性 1:

これは実際にはコンパイラのバグであり、テンプレート解決の問題に起因しています。

コンパイラは、必要に応じてムーブ コンストラクターを暗黙的に定義しようとします。これは、クラス定義にコピーできない型があり、そのクラスへの割り当てがコード内で行われる場合に行います。

これらの 2 つの条件が満たされると、move-constructor の定義に進みますが、テンプレートの実際の型は気にせず、実際にstd::unique_ptrstd::vectorのコピーを定義するクラス自体だけを気にしているようです。constructor, so the VCC tries to use it, which fails because of the missing copy constructor in

または、move-constructor の定義を完全にスキップして、copy-constructor を使用しようとするだけで、同じエラーが発生します。

可能性 2:

Microsoft STL の実装に怪しいものがあります。これは単なる手がかりであり、それがどのように機能したかを正確に説明することはできませんでしたが、それでも私には可能性があるようです.

この混乱を避けるには?

上記のように、独自のムーブ コンストラクターを簡単に定義できます。


編集:

ある特定の問題に行き着くようです。元の回答は以下に掲載されています。

Visual Studio (2013) で、新しい Win32 コンソール アプリケーションを作成し、設定を変更せず、これをメインにします.cpp

// ConsoleApplication2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <vector>
#include <memory>

class Foo { };

class MyClass
{
public:
    MyClass(std::vector<std::unique_ptr<Foo>> foos) :
        foos_(std::move(foos))
    {};

    std::vector<std::unique_ptr<Foo>> foos_;
};

int _tmain(int argc, _TCHAR* argv[])
{
    auto test = MyClass(std::vector<std::unique_ptr<Foo>>()); //remove this, and all works fine!
    return 0;
}

コンパイルしようとすると、次のエラーが発生します (gcc で確実に動作します!)。

1>  ConsoleApplication2.cpp
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(593): error C2280: 'std::unique_ptr<Foo,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
1>          with
1>          [
1>              _Ty=Foo
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<Foo,std::default_delete<_Ty>>::unique_ptr'
1>          with
1>          [
1>              _Ty=Foo
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(592) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1>          with
1>          [
1>              _Ty=std::unique_ptr<Foo,std::default_delete<Foo>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Foo,std::default_delete<Foo>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Foo,std::default_delete<Foo>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::unique_ptr<Foo,std::default_delete<Foo>>>
1>          ]
1>          c:\users\felix\source\repos\infinite whitewursht\infinitewhitewursht\consoleapplication2\consoleapplication2.cpp(18) : see reference to class template instantiation 'std::vector<std::unique_ptr<Foo,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
1>          with
1>          [
1>              _Ty=Foo
1>          ]

次のようなコンストラクタがあるとします。

MyClass(vector<unique_ptr<Foo>> foos) :
    foos_(std::move(foos))
{};

この単純なセットアップでは、すべてが正常にコンパイルされます。このコンストラクターのような呼び出しはMyClass(vector<unique_ptr<Foo>>);成功し、期待どおりに動作します。foosしかし、デフォルトのパラメーターとして使用したいと思います。

のデフォルト値を達成するにはどうすればよいfoosですか?

これは私が思いついたものです:

MyClass(vector<unique_ptr<Foo>> foos = vector<unique_ptr<Foo>>()) :
    foos_(std::move(foos))
{};

しかし残念ながら、これはうまくいきません。理由はわかりませんが、誰かがこれに光を当てることができればいいと思います.

次の 2 つの試みは回避策であり、実際のデフォルト パラメータではありません。

MyClass() :
    foos_() //or foos_(vector<unique_ptr<Foo>>())
{};

どちらも働かないでください。これらのアプローチはどちらも、コンパイラからのエラー メッセージと、最も興味深い部分である長い出力につながります。

c:\users\ username \source\repos\myProject\myProject\MyClass.h(47) : クラス テンプレートのインスタンス化への参照を参照してください

47 は、実際のベクトル定義の行番号ですMyClass

vector<unique_ptr<GameObject>> foos_;

だから私の推測では、これは本当に私が初期化で大きな間違いをしているということです。

また、VS2013でコンパイルしています。

エラー全体:

GameObject.cpp
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(593): error         C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(592) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1>          with
1>          [
1>              _Ty=std::unique_ptr<int,std::default_delete<int>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int,std::default_delete<int>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<int,std::default_delete<int>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::unique_ptr<int,std::default_delete<int>>>
1>          ]
1>          c:\users\felix\source\repos\infinite whitewursht\infinitewhitewursht\infinitewhitewursht\gameobject.h(47) : see reference to class template instantiation 'std::vector<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]
4

1 に答える 1

2

ベクトルをまったくとらず、デフォルトでベクトルを初期化するコンストラクター オーバーロードを記述します (空のベクトルに)。

MyClass() : foos_{}
{}
于 2014-04-24T23:07:12.117 に答える