Programing

기본 클래스가 아닌데 파생 클래스 이동을 구성 할 수있는 이유는 무엇입니까?

crosscheck 2020. 12. 27. 11:51
반응형

기본 클래스가 아닌데 파생 클래스 이동을 구성 할 수있는 이유는 무엇입니까?


다음 예를 고려하십시오.

#include <iostream>
#include <string>
#include <utility>

template <typename Base> struct Foo : public Base {
    using Base::Base;
};

struct Bar {
    Bar(const Bar&) { }
    Bar(Bar&&) = delete;
};

int main() {
    std::cout << std::is_move_constructible<Bar>::value << std::endl; // NO
    std::cout << std::is_move_constructible<Foo<Bar>>::value << std::endl; // YES. Why?!
}

기본 클래스가 이동 구성이 불가능 함에도 불구하고 컴파일러가 이동 생성자를 생성하는 이유는 무엇입니까?

표준에 있습니까 아니면 컴파일러 버그입니까? 기본에서 파생 클래스로 이동 구성을 "완벽하게 전파"할 수 있습니까?


때문에:

삭제 된 것으로 정의 된 기본 이동 생성자는 오버로드 확인에서 무시됩니다.

([class.copy] / 11)

Bar의 이동 생성자가 명시 적으로 삭제 되었으므로 Bar이동할 수 없습니다. 그러나 Foo<Bar>의 이동 생성자는 멤버를 이동할 수 없기 때문에 기본값으로 암시 적으로 선언 암시 적으로 삭제됩니다Bar . 따라서 Foo<Bar>복사 생성자를 사용하여 이동할 수 있습니다.

편집 : 또한 상속 생성자 선언이 using Base::Base기본, 복사 또는 이동 생성자를 상속하지 않는다는 중요한 사실을 언급하는 것을 잊었 으므로 Foo<Bar>명시 적으로 삭제 된 이동 생성자가에서 상속되지 않습니다 Bar.


1. 행동 std::is_move_constructible

이것은 std :: is_move_constructible 의 예상 동작입니다 .

이동 생성자가 없지만 const T&인수 를 허용하는 복사 생성자가있는 유형은 std::is_move_constructible.

즉, 복사 생성자를 사용하면 Trvalue reference에서 생성 할 수 있습니다 T&&. 그리고 Foo<Bar>암시 적으로 선언 복사 생성자를 .

2. 암시 적으로 선언 된 이동 생성자 Foo<Bar>

기본 클래스가 이동 구성이 불가능 함에도 불구하고 컴파일러가 이동 생성자를 생성하는 이유는 무엇입니까?

실제로의 이동 생성자는 deletedFoo<Bar> 로 정의되지만 삭제 된 암시 적으로 선언 된 이동 생성자는 오버로드 확인에서 무시됩니다.

클래스 T대한 암시 적으로 선언되거나 기본 이동 생성자 는 다음 중 하나가 참인 경우 삭제 된 것으로 정의됩니다.

...
T has direct or virtual base class that cannot be moved (has deleted, inaccessible, or ambiguous move constructors); 
...

삭제 된 암시 적으로 선언 된 이동 생성자는 오버로드 확인에서 무시됩니다 (그렇지 않으면 rvalue에서 복사 초기화가 방지 됨).

3. Bar사이의 다른 행동Foo<Bar>

의 이동 생성자는 명시 적으로 Bar선언 deleted되고의 이동 생성자 Foo<Bar>는 암시 적으로 선언되고로 정의됩니다 deleted. 요점은 삭제 된 암시 적으로 선언 된 이동 생성자가 오버로드 해결에 의해 무시 되므로 Foo<Bar>복사 생성자 로 구성을 이동할 수 있다는 것 입니다. 그러나 명시 적으로 삭제 된 이동 생성자는 오버로드 해결에 참여합니다. 즉, 생성자를 이동하려고 할 때 Bar삭제 된 이동 생성자가 선택되고 프로그램이 잘못 구성됩니다.

그렇기 때문에 Foo<Bar>이동 시공이 가능하지만 Bar그렇지 않습니다.

표준에는 이것에 대한 명시적인 진술이 있습니다. $ 12.8 / 11 클래스 개체 복사 및 이동 [class.copy]

삭제됨으로 정의 된 기본 이동 생성자는 오버로드 확인 ([over.match], [over.over])에서 무시됩니다. [참고 : 삭제 된 이동 생성자는 복사 생성자를 대신 사용할 수있는 rvalue의 초기화를 방해합니다. — 끝 참고]

참조 URL : https://stackoverflow.com/questions/39139087/why-is-derived-class-move-constructible-when-base-class-isnt

반응형