문제

학습 운동으로서, 나는 자동 유형 변환이 C ++에서 어떻게 작동하는지 살펴보고 있습니다. 나 알다 이러한 자동 유형 변환은 일반적으로 피해야하지만, 어쨌든 작동 방식을 이해함으로써 C ++에 대한 지식을 높이고 싶습니다.

나는 a StdStringConverter 자동으로 변환 할 수있는 클래스 std::string, 그러나 컴파일러 (Debian의 G ++ 4.3.4)는 객체를 실제와 비교할 때 변환을 수행하지 않는 것 같습니다. std::string (임시 대상의 참조와 불필요한 생성의 부족을 무시하십시오) :

#include <string>

class StdStringConverter
{
public:
    explicit StdStringConverter(std::string name) : m_name(name) {}
    operator const std::string () const { return m_name; }
private:
    std::string m_name;
};

int main()
{
    StdStringConverter converter(std::string("Me"));
    const std::string name = "Me";
    // Next line causes compiler error:
    // no match for 'operator==' in 'converter == name'
    return (converter == name) ? 0 : 1;
}

반면에, 내가 그것을 약간 바꾸면 CStringConverter 클래스, 자동 변환 하다 비교하더라도 발생합니다 char 포인터는 아마도 내가 의도 한 것이 아닐 것입니다.

#include <string>

class CStringConverter
{
public:
    explicit CStringConverter(std::string name) : m_name(name) {}
    operator const char* () const { return m_name.c_str(); }
private:
    std::string m_name;
};

int main()
{
    CStringConverter converter(std::string("Me"));
    const char* name = "Me";
    // Next line compiles fine, but they are not equal because the
    // pointers don't match.
    return (converter == name) ? 0 : 1;
}

a의 차이점에 특별한 것이 있습니까? std::string 그리고 a char* 이러한 맥락에서 컴파일러가 동일하게 취급하지 않게 하는가?

도움이 되었습니까?

해결책

문제는 std :: string이 실제로 클래스 템플릿 std :: basic_string의 인스턴스라는 사실 때문입니다. 네임 스페이스에서 사용할 수있는 연산자 == STD는 2 개의 std :: basic_string 템플릿을 사용합니다.


template<class charT, class traits, class Allocator>
bool operator==(const basic_string& lhs,
                const basic_string& rhs);

이 버전의 Operator ==가 STD :: String에서 특별히 과부하 된 경우 코드가 정상입니다. 그러나 컴파일러가 std :: basic_string의 템플릿 매개 변수에서 템플릿 인수 공제를 수행 해야하는 경우는 그렇지 않습니다. 따라서 변환 연산자의 반환이 가능하다는 것을 이해할 수 있습니다.

그러나 컴파일러는 그렇게하지 않습니다. 표준의 어느 부분이 정확하게 나타나는지 모르겠습니다. 그러나 일반적인 아이디어는 그러한 전환이 비 테일 플레이트 유형에만 효과가 있다는 것입니다.

내가 제안 할 수있는 한 가지는 당신이 네임 스페이스에 stdstringConverter를 배치하고 해당 네임 스페이스의 std :: string에 연산자 == 버전을 제공하는 것입니다. 이런 식으로 컴파일러가 해당 ADL (인수 종속 조회)과 같은 표현식을 찾으면 모든 것이 잘 작동합니다.


#include <string>

namespace n1 {

class StdStringConverter
{
public:
    explicit StdStringConverter(std::string name) : m_name(name) {}
    operator std::string () { return m_name; }
private:
    std::string m_name;
};

bool operator==(std::string const& a, std::string const& b)
{
  return a == b; //EDIT: See Paul's comment on std::operator== here.
}

}

int main()
{
    using namespace n1;
    StdStringConverter converter(std::string("Me"));
    std::string name = "Me";
    return (converter == name) ? 0 : 1;   
}

다른 팁

첫 번째 예에서 두 비교 클래스 (String 및 StdstringConverter)는 유형 변환을 위해 컴파일러로부터 특별한 처리를 얻지 못합니다. 즉, 당신이 만든 운영자 과부하가 트리거되지 않음을 의미합니다. 컴파일러는 Operator == Overloads의 목록을 검토하고 그중 중 비는 stdstringconverter를 사용하여 소리를 지르기 위해 소리칩니다.

두 번째 예에서 이름은 char *입니다. 원시 유형이므로 컴파일러는 비 원시를 숯으로 변환하려고 시도합니다. 재정의가 있으므로 작동하고 주소를 비교합니다.

컴파일러는 원시 유형을 포함하지 않는 작업에서 주조를 명시하지 않습니다. 그것이 할 일은 생성자를 사용하여 유형을 일치 시키려고 시도하는 것입니다. 예를 들어 첫 번째 예제를 변경하면 다음과 같습니다.

#include <string>

class StdStringConverter
{
public:
    StdStringConverter(std::string name) : m_name(name) {}
    bool operator==(const StdStringConverter &name) { return m_name == name.m_name; }
    operator const std::string () const { return m_name; }
private:
    std::string m_name;
};

int main()
{
    StdStringConverter converter(std::string("Me"));
    const std::string name = "Me";
    // Next line causes compiler error:
    // no match for 'operator==' in 'converter == name'
    return (converter == name) ? 0 : 1;
}

이제 프로그램은 0을 반환합니다. 생성자는 이제 명시 적이지 않기 때문에 컴파일러는 문자열을 stdstringconverter로 변환하기 위해이를 사용하려고 시도합니다. 이제 stdstringconverter에 연산자 ==가 있으므로 모든 것이 작동합니다.

여러 가지 요인이 있습니다. 따라서 반환 명령문을 변경하면

return (std :: operator == (이름, 이름))? 0 : 1;

분명히 같은 일을하지는 않지만 컴파일합니다. 반면에

return (std :: Operator == (변환기, 이름))? 0 : 1;

더 흥미로운 오류 메시지를 제공하지는 않습니다

'Operator == (stdstringconverter &, const std :: string &)에 대한 호출 기능 없음

연산자 ==가 Basic_string <>에서 템플릿으로 부팅 할 템플릿 매개 변수가있는 것을 상기시켜줍니다. std :: string 대신 예제에서 int를 사용하는 경우 컴파일러는 불평하지 않습니다.

std :: 문자열로 원하는 효과를 얻는 방법은 더 흥미 롭습니다 ...

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