2014-02-28 2 views
0

아래의 텍스트는 David Vandevoorde 및 Nicolai Josuttis의 "C++ Templates The Complete Guide"책의 부록 B에 있습니다.사용자 정의 변환이 표준 정수 변환보다 더 잘 일치하는 이유는 무엇입니까?

B.2 간체 과부하 해결이 첫 번째 원칙을 감안할 때

, 우리는 주어진 인수가 가능한 후보의 해당 매개 변수와 일치 얼마나 잘 지정으로 남아 있습니다.

  • 완벽한 일치를 (최고에서 최악으로) 다음과 같이 첫 번째 근사치로서 우리는 가능한 일치를 순위를 할 수 있습니다. 매개 변수에는 표현식의 유형이 있거나 표현식의 유형에 대한 참조 인 유형이 있습니다 (가능한 경우 const 및/또는 volatile 한정자가 추가 된 ).
  • 약간의 조정이 필요합니다. 예를 들어, 첫 번째 요소에 대한 포인터에 대한 배열 변수의 감쇠 또는 int const * const * 매개 변수에 int ** 형식의 인수를 일치시키는 const의 추가 ( )가 포함됩니다.
  • 프로모션과 일치해야합니다. 승격은 작은 정수 유형 (예 : bool, char, short 및 때때로 enumeration)을 int, unsigned int, long 또는 unsigned long으로 변환하고 float를 double로 변환하는 것을 포함하는 일종의 암시 적 변환입니다.
  • 표준 변환과 만 일치합니다. 여기에는 표준 변환 (int와 같은 부동 소수점 형)이 포함되지만 암시적인 호출은 변환 연산자 또는 변환 생성자로 제외됩니다.
  • 사용자 정의 변환과 일치합니다. 이것은 어떤 종류의 암시적인 변환도 허용합니다.
  • 줄임표와 일치하십시오. 생략 부호 매개 변수는 거의 모든 유형과 일치 할 수 있지만 (비 POD 클래스 유형의 경우 정의되지 않은 동작이 발생 함)

몇 페이지 나중에 책은 다음의 예와 텍스트 (강조 광산)를 보여줍니다 : 처음에

class BadString { 
    public: 
    BadString(char const*); 
    ... 
    // character access through subscripting: 
    char& operator[] (size_t); // (1) 
    char const& operator[] (size_t) const; 
    // implicit conversion to null-terminated byte string: 
    operator char*(); // (2) 
    operator char const*(); 
    ... 
}; 
int main() 
{ 
    BadString str("correkt"); 
    str[5] = 'c'; // possibly an overload resolution ambiguity! 
} 

를, 아무것도 식 STR에 대한 모호한 것 같다 [5]. (1)의 하위 연산자는 완벽한 일치로 보입니다. 그러나 인수 5에는 int 유형이 있고 연산자에는 부호없는 정수 유형 (size_t 및 std :: size_t 은 대개 unsigned int 또는 unsigned long 유형이 있지만 int 유형은 필요하지 않음)이 필요하기 때문에 은 완벽하지 않습니다. 여전히 간단한 표준 정수 변환은 (1) 쉽게 실행 가능하게 만듭니다. 그러나 또 다른 실행 가능한 후보가 있습니다 : 내장 된 첨자 연산자. 실제로 암시 적 변환 연산자를 (암시 적 멤버 함수 인수)에 적용하면 포인터 을 얻습니다. 이제 내장 첨자 연산자가 적용됩니다. 이 내장형 연산자는 ptrdiff_t 유형의 인수를 취합니다. 많은 플랫폼에서 은 int와 동일하므로 인수 5와 완벽하게 일치합니다. 내장형 첨자 연산자가 사용자 정의 변환)을 사용하는 경우 실제 첨자에 대해 (1)에 정의 된 연산자보다 더 좋게 일치! 따라서 잠재적 인 모호성.

+1

무엇을 묻고 싶습니까? –

답변

0

첫 번째 목록은 간체 과부하 해결입니다.

str[(ptrdiff_t)5] = 'c'; // definitely an overload resolution ambiguity! 

지금은 g++에서 얻을 메시지는 다음과 같습니다 :

은의 변경하자, intptrdiff_t과 동일 여부에 대해 한 줄을 "가능성"과 "가능성"을 제거하려면 warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default]

--pedantic-errors은 오류 경고를 표시합니다.

표준에 들어가기 전에 단순화 된 목록은 이야기의 일부일뿐입니다. 이 목록은 A에서 B로 갈 때 선호 할 수있는 몇 가지 경로 중 어느 것이지 알려주지 만 C에서 D까지의 여행에서 A에서 B 로의 여행을 선호할지 여부를 알려주지 않습니다.

현상 (같은 g ++ 메시지) 더 분명히 여기 :

struct S { 
    explicit S(int) {} 
    operator int() { return 0; } 
}; 

void foo(const S&, long) { } 
void foo(int, int) { } 

int main() { 
    S s(0); 
    foo(s, 1); 
} 

우리가 암시 적으로 과부하를 선택하기 위해 변환 할 수있는 인수의 선택의 여지가있을 때 때문에 다시 foo에 대한 호출이 모호 규칙 돈 't은 두 가벼운 변환을 선택하고 해당 변환을 요구하는 인수를 변환합니다. "

이제 표준 표창장을 올려주세요거야,하지만 난 그게 없는 내가 요약 ;-)

그것을 찾는하지에 대한 변명으로 건초를 칠 필요는 사실을 사용하여야한다 여기에 "사용자 정의 변환은 표준 정수 변환보다 더 적합합니다"라는 것이 참입니다. 그러나이 경우 두 가지 가능한 과부하가 표준에 따라 동일하게 정의되므로 호출이 모호합니다.

0
str.operator[](size_t(5)); 

쓰기 확실한 방법으로 코드 그리고 당신은이 모든 것들에 대해 걱정 할 필요가 있습니다 : 에 관한 일을 훨씬 더이 있습니다.