2013-03-09 2 views
4

파생 클래스에 소멸자를 추가하면 정의 된 이동 도구 대신 복사 ctor를 사용할 때 컴파일러 오류가 발생합니다 (gcc 4.7 사용).파생 된 경우 소멸자가 정의 된 경우 move ctor 대신 copy ctor 사용

#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) 

답변

1

오류는 정확합니다. 이동 생성자는 클래스에 사용자 정의 소멸자가 없을 때만 암시 적으로 생성됩니다. 소멸자를 추가하면 기본 이동 생성자가 표시되지 않고 복사 생성자가 시도됩니다. Derived은 복사 가능하거나 이동 가능하지 않으므로 클래스에 복사 불가능 기본 클래스가있는 경우 기본 복사 생성자 생성이 억제됩니다.

해결 방법은 단순히 이동 생성자를 Derived에 추가하는 것입니다.

+0

기본 멤버가 아닌 파생 클래스의 이동 생성자를 선언 할 필요가 없습니다. 'Derived (Derived && other) : Base (other) {}'은 기본 클래스 복사 생성자를 호출하므로 명시 적으로 std :: move 대신 작동하도록 시도했습니다. 그 맞습니까? – goji

+1

@ 트로이 예, 맞습니다. '이동'이 필요합니다. 지금까지 이동 생성자를 가질 필요가 없었던 이유는 컴파일러가 표준에 대한보다 엄격한 준수를 시작하기 때문입니다. –

+1

'= default'라고해도 좋을 것 같습니다. :) – goji

관련 문제