4

派生クラスにデストラクタを追加すると、定義されたmovectorの代わりにcopyctorを使用しようとすると、コンパイラエラーが発生します(gcc 4.7を使用)。

#include <utility>
#include <iostream>

template <typename T>
struct Base 
{
  T value;

  Base(T&& value) :
    value(value)
  {
    std::cout << "base ctor" << std::endl;
  }

  Base& operator=(const Base&) = delete;
  Base(const Base&) = delete;

  Base& operator=(Base&& rhs)
  {
    value = rhs.value;
    std::cout << "move assignment" << std::endl;
  }

  Base(Base&& other) :
    value(other.value)
  {
    std::cout << "move ctor" << std::endl;
  }

  virtual ~Base()
  {
    std::cout << "base dtor" << std::endl;
  }
};

template <typename T>
struct Derived : public Base<T>
{
  Derived(T&& value) :
    Base<T>(std::forward<T>(value))
  {
    std::cout << "derived ctor" << std::endl;
  }

  ~Derived()
  {
    std::cout << "derived dtor" << std::endl;
  }
};

template <typename T>
Derived<T> MakeDerived(T&& value)
{
  return Derived<T>(std::forward<T>(value));
}

struct Dummy {};

int main()
{
  auto test = MakeDerived(Dummy());
}

このコードは、gcc-4.5およびgcc-4.6で正常にコンパイルされます。gcc-4.7のエラーは次のとおりです。

test.cpp: In function ‘int main()’:
test.cpp:61:34: error: use of deleted function ‘Derived<Dummy>::Derived(const Derived<Dummy>&)’
test.cpp:37:8: note: ‘Derived<Dummy>::Derived(const Derived<Dummy>&)’ is implicitly deleted because the default definition would be ill-formed:
test.cpp:37:8: error: use of deleted function ‘Base<T>::Base(const Base<T>&) [with T = Dummy; Base<T> = Base<Dummy>]’
test.cpp:16:3: error: declared here
test.cpp: In instantiation of ‘Derived<T> MakeDerived(T&&) [with T = Dummy]’:
test.cpp:61:34:   required from here
test.cpp:54:43: error: use of deleted function ‘Derived<Dummy>::Derived(const Derived<Dummy>&)’

私はここで何かが足りないのですか、それともこれもgcc 4.7で正常にコンパイルする必要がありますか?Derivedクラスのデストラクタをコメントアウトすると、すべてうまくいきます。

gcc version 4.5.3 (Ubuntu/Linaro 4.5.3-12ubuntu2) 
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 
gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-11precise2) 
4

1 に答える 1

1

エラーは正しいです。移動コンストラクタは、クラスにユーザー定義のデストラクタがない場合にのみ暗黙的に生成されます。デストラクタを追加すると、デフォルトのmove-constructorが抑制され、copyコンストラクタが試行されます。クラスにコピー不可能な基本クラスがある場合、デフォルトのコピーコンストラクターの生成は抑制されるためDerived、コピー可能でも移動可能でもありません。

解決策は、move-constructorをに追加することDerivedです。

于 2013-03-09T03:50:20.797 に答える