문제

업데이트 : 해결 된 코드 예제 해결 방법 (원래 의도). Rlbond의 답변을 본 후 이것을 실현했습니다.

나는 사용법을 통합하려고 노력하고 있습니다 auto_ptr 이 스레드의 권장 사항을 기반으로 내 코드에서 다음과 같습니다.

메소드 인터페이스를 통해 C ++ 인수의 사용을 표현합니다.

그러나 Visual Studio 6.0으로 컴파일 할 때 예상치 못한 컴파일 오류를 받고 있습니다. 과제/사본을 다룰 때 문제가 있습니다. std::auto_ptr 파생 유형의 a std::auto_ptr 기본 유형의. 이것이 내 컴파일러에만 해당되는 문제입니까?

Boost를 사용하는 것이 강력한 권장 사항이 있다는 것을 알고 있지만 내 프로젝트에서는 옵션이 아닙니다. 내가 여전히 사용하고 싶다면 auto_ptr, 나는 전화의 해결 방법을 사용해야합니까? std::auto_ptr::release()? 지금까지 발생한 것에서이 문제로 인해 컴파일러 오류가 발생하므로 쉽게 잡을 수 있습니다. 그러나 릴리스 릴리스 협약을 채택하여 기본 유형의 'auto_ptr'에 할당을 채택하여 유지 보수 문제에 노출 될 수 있습니까? 특히 다른 컴파일러로 구축 된 경우 (다른 컴파일러 에이 문제가 없다고 가정).

만약 release() 내 상황으로 인해 해결 방법이 좋지 않습니다. 소유권 이전을 설명하기 위해 다른 협약을 사용해야합니까?

다음은 문제를 보여주는 예입니다.

#include "stdafx.h"
#include <memory>

struct A
{
    int x;
};

struct B : public A
{
    int y;
};

typedef std::auto_ptr<A> AutoA;
typedef std::auto_ptr<B> AutoB;

void sink(AutoA a)
{
    //Some Code....
}

int main(int argc, char* argv[])
{
    //Raws to auto ptr
    AutoA a_raw_to_a_auto(new A());
    AutoB b_raw_to_b_auto(new B());
    AutoA b_raw_to_a_auto(new B());

    //autos to same type autos
    AutoA a_auto_to_a_auto(a_raw_to_a_auto);
    AutoB b_auto_to_b_auto(b_raw_to_b_auto);

    //raw derive to auto base
    AutoB b_auto(new B());

    //auto derive to auto base
    AutoA b_auto_to_a_auto(b_auto);  //fails to compile

    //workaround to avoid compile error.
    AutoB b_workaround(new B());
    AutoA b_auto_to_a_auto_workaround(b_workaround.release());

    sink(a_raw_to_a_auto);
    sink(b_raw_to_b_auto);  //fails to compile

    return 0;
}

컴파일 오류 :

Compiling...
Sandbox.cpp
C:\Program Files\Microsoft Visual Studio\MyProjects\Sandbox\Sandbox.cpp(40) : error C2664: '__thiscall std::auto_ptr<struct A>::std::auto_ptr<struct A>(struct A *)' : cannot convert parameter 1 from 'class std::auto_ptr<struct B>' to 'struct A *'
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
C:\Program Files\Microsoft Visual Studio\MyProjects\Sandbox\Sandbox.cpp(47) : error C2664: 'sink' : cannot convert parameter 1 from 'class std::auto_ptr<struct B>' to 'class std::auto_ptr<struct A>'
        No constructor could take the source type, or constructor overload resolution was ambiguous
Error executing cl.exe.

Sandbox.exe - 2 error(s), 0 warning(s)
도움이 되었습니까?

해결책

첫 번째는 쉽습니다.

AutoA b_auto_to_a_auto(b_auto);  //fails to compile

이것은 필요하기 때문에 VC6에서 실패합니다 멤버 기능 템플릿, VC6의 표준 라이브러리가 지원하지 않는 것. 그러나 표준 호환 컴파일러에서 컴파일합니다.

해결 방법 :

AutoA b_auto_to_a_auto( b_auto.release() );

두 번째는 훨씬 더 미묘합니다 :)

sink(b_raw_to_b_auto);  //fails to compile

암시 적 변환이 진행되고 있기 때문에 표준 호환 컴파일러에서 컴파일해서는 안됩니다. 컴파일러가 위를 바꿉니다

sink( std::auto_ptr<A>( b_raw_to_b_auto ) );

하지만, sink 테이크 std::auto_ptr<A> ~에 의해 , 그래서 임시 std::auto_ptr<A> 컴파일러에 의해 암시 적으로 생성되어야합니다 카피로 구성되었습니다 논쟁으로 sink. 자, 그와 같은 시간이 있습니다 rvalues. rvalues는 정점이 아닌 참조에 묶이지 않지만 std::auto_ptr"S"Copy Constructor "는 인수를 가져옵니다. 비정규 참조.

당신은 간다 - 오류를 컴파일하십시오. Afaics 이것은 표준 정보 행동입니다. C ++ -0X "Move Semantics"는 RValue 참조를 취하는 "복사 생성자"를 추가하여이를 수정합니다. std::auto_ptr 앞으로도 여전히 무엇을받을 것입니다 std::shared_ptr 그리고 다.

두 번째 해결 방법 :

AutoA tmp( b_raw_to_b_auto/*.release() for VC6*/ );
sink( tmp );

다른 팁

AutoA b_auto_to_a_auto(b_auto);  //fails to compile

sink(b_raw_to_b_auto);  //fails to compile

Pavel Minaev는 내가 실제로 몰랐던 것을 지적합니다.

첫 번째 호출은 b*에서 a*로 암시 적 변환이 있기 때문에 컴파일해야합니다. 그러나 두 번째는 컴파일하지 않습니다. 다음은 다음과 같습니다.

sink(static_cast<AutoA>(b_raw_to_b_auto));

VC6은 템플릿에 능숙하지 않은 것으로 유명합니다.

코드 기반을 실제로 작동하고 RAII 기술을 사용하기 시작하는 코드 기반으로 업그레이드하는 것이 좋습니다. boost::shared_ptr. 나는 당신이 당신이 할 수 없다고 말하고, 그것이 어렵다는 것을 알고 있지만, 당신은 사실상 메모리 누출이없고 수많은 버그를 가질 것입니다.

다시 한번, 완전한 기능이 없어도 사용할 수 있습니다. auto_ptr?

여기에는 두 가지 문제가 있습니다. 우선, 이것은 :

AutoA b_auto_to_a_auto(b_auto);  

그것은이다 완벽하게 표준 준수 그리고 컴파일해야합니다. 이유를 설명하겠습니다. ISO C ++ 표준은 (20.4.5.1 [lib.auto.ptr.cons]/4-6) 다음 생성자를 지정합니다. auto_ptr<X> (다른 것 중에서);

template<class Y> auto_ptr(auto_ptr<Y>&) throw();

주목하십시오 Y 다른 유형입니다 X 여기. 그리고 표준은 다음과 같이 말합니다.

요구 사항 : y*는 암시 적으로 x*로 변환 될 수 있습니다.

여기서주의를 기울여야 할 유일한 것은 생성자 인수가 참조로 참조한다는 것입니다. 귀하의 경우에, 이것은 문제가되지 않지만 (당신은 거기에 비 초가 변수를 전달하기 때문에) 다음 부분에는 중요해집니다. 여기서 결론을 내리려면 : 당신이보고있는 것은입니다 비표준 행동 VC6에서. 그것 ~해야 한다 호환 컴파일러에서 컴파일하고 VC7 이상에서 컴파일됩니다). 이제 두 번째로 :

sink(b_raw_to_b_auto);  //fails to compile

이것은 실제로 Mmutz에 의해 완벽하게 설명되어 있으므로 여기서는 자세히 설명하지 않을 것입니다. 그의 대답을 참조하십시오. 결론적으로 : 예,이 라인은 컴파일해서는 안되며 준수 컴파일러 (또는 VC6)에서 찾지 않아야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top