문제

힙으로 배치 된 물체 주위에 래퍼 역할을하기 위해 클래스를 작성할 때, 나는이 간단한 예로 줄일 수있는 암시 적 유형 변환에 문제가 발생했습니다.

아래 코드 아래에서 래퍼 클래스는 힙으로 배치 된 객체를 관리하고 암시 적으로 해당 객체에 대한 참조로 변환합니다. 이것은 암시 적 변환이 발생하기 때문에 함수 쓰기 (...)에 대한 인수로서 래퍼 객체를 전달할 수있게한다.

그러나 명시 적 캐스트가 이루어지지 않는 한 (MSVC8.0, Intel 9.1 및 GCC 4.2.1 컴파일러로 확인).

(1)이 경우 암시 적 변환이 실패하는 이유는 무엇입니까? (2) 인수 의존적 조회와 관련이있을 수 있습니까? 그리고 (3) 명백한 캐스트 없이이 일을하기 위해 할 수있는 일이 있습니까?

#include <fstream>

template <typename T>
class wrapper
{
    T* t;
  public:
    explicit wrapper(T * const p) : t(p) { }
    ~wrapper() { delete t; }
    operator T & () const { return *t; }
};

void write(std::ostream& os)
{
    os << "(1) Hello, world!\n";
}

int main()
{
    wrapper<std::ostream> file(new std::ofstream("test.txt"));

    write(file);
    static_cast<std::ostream&>( file ) << "(2) Hello, world!\n";
    // file << "(3) This line doesn't compile!\n";
}
도움이 되었습니까?

해결책

당신이 당신의 운영자를 해결하려고 노력하기 때문에 실패합니다. wrapper<T> 존재하지 않는 클래스. 캐스트없이 작동하기를 원한다면 다음과 같은 것을 모을 수 있습니다.

template<typename X> wrapper<T> &operator <<(X &param) const {
    return t << param;
}

불행히도 컴파일 시간에 리턴 유형을 해결하는 방법을 모릅니다. 다행히도 대부분의 경우이 경우를 포함하여 객체와 동일한 유형입니다. ostream.

편집하다: 대시-톰-뱅의 제안에 의해 수정 된 코드. 반환 유형이 변경되었습니다 wrapper<T> &.

다른 팁

컴파일러는이를 결정하기에 충분한 컨텍스트가 없습니다 operator& 유효한 변환을 할 것입니다. 그렇습니다. 이것은 인수 의존적 조회와 관련이 있다고 생각합니다. 컴파일러는 operator<< 비를 받아 들일 수 있습니다const wrapper<std::ostream> 첫 번째 매개 변수로.

문제는 컴파일 타임 제약 조건을 유지하는 것과 관련이 있다고 생각합니다. 예에서는 컴파일러가 먼저 찾아야합니다. 모두 가능한 연산자 <<. 그런 다음 각각의 경우 객체를 각 연산자 <<이 허용 할 수있는 유형으로 자동으로 (직접 또는 간접적으로) 자동으로 변환 할 수 있는지 시도해야합니다.

이 테스트는 정말 복잡 할 수 있으며, 이것이 합리적인 컴파일 시간을 제공하는 것으로 제한된다고 생각합니다.

일부 테스트 후에는 더 단순한 예제가 문제의 원인을 식별합니다. 컴파일러는 템플릿 인수를 추론 할 수 없습니다 T 안에 f2(const bar<T>&) 아래의 암시 적 변환에서 wrapper<bar<int> > 에게 bar<int>&.

template <typename T>
class wrapper
{
    T* t;
  public:
    explicit wrapper(T * const p) : t(p) { }
    ~wrapper() { delete t; }
    operator T & () const { return *t; }
};

class foo { };

template <typename T> class bar { };

void f1(const foo& s) { }
template <typename T> void f2(const bar<T>& s) { }
void f3(const bar<int>& s) { }

int main()
{
    wrapper<foo> s1(new foo());
    f1(s1);

    wrapper<bar<int> > s2(new bar<int>());
    //f2(s2); // FAILS
    f2<int>(s2); // OK
    f3(s2);
}

원래 예에서 std::ostream 실제로 a typedef 템플릿 클래스의 경우 std::basic_ostream<..>, 템플릿 함수를 호출 할 때 동일한 상황이 적용됩니다. operator<<.

삽입 연산자의 서명을 확인하십시오.

확인 C ++ 03 표준을 사용하여 Char* 출력 연산자의 서명은 다음과 같습니다.

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);

실제로는 중요한 참조를 취합니다. 따라서 변환 연산자가 일치하지 않습니다.

의견에 언급 된 바와 같이 : 이것은 관련이 없습니다.

적용된 전환에 대한 표준에는 다양한 제한이 있습니다 ... 아마도 최대 하나를 적용해야 할 때는 암시 적 변환 (연산자 및 기본 유형으로 캐스트)이 필요할 수 있습니다.

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