2014-09-23 2 views
30

다음 코드는 char에 대한 암시 적 변환으로 인해 컴파일됩니다. 왜 내가 암시 적으로 변환을 기대하기 때문에 (그리고 실패 할 것으로 예상하는지) char const*에서 size_t으로 넘어갈 이유가 확실하지 않습니다.C++ 예기치 않은 implict 변환

#include <cstddef> 

struct foo 
{ 
    int operator[](size_t i) const { return 1; } 
    operator char() const { return 'a'; } 
}; 

int main() 
{ 
    foo f; 
    f["hello"]; // compilation error desired here 
} 

여기에 암시 적으로 변환이 가능한 이유는 무엇입니까? operator char을 제거하거나 explicit으로 만들면 원하는 위치에서 컴파일이 실패합니다.

이 코드가 실제로 추출되는 클래스에는 암시 적 변환과 operator[]이 모두 필요합니다. 그렇다면 전환을 명시 적으로 나타내지 않고 동작을 방지 할 수있는 방법이 있습니까?

+1

당신이 추가하는 시도 유무 : 그래서 더 ARGE 값 (포인터의 값) [] 과부하 동안 조심하고있는 경우, 사실이 상위 경계에 대한 을 확인, 사실 인덱스 값은 알 것이다 private 연산자 [] (char const *)'? –

답변

34

줄을 컴파일하는 이유는 암시 적 변환을 사용하면 'a'["hello"];으로 다시 해석 할 수 있으며 이는 다시 컴파일하여 *(('a')+("hello"));을 작성하는 것과 같습니다. 표준에 대한

발췌 :

5.2.1 첨자 :

... 식 E1 [E2]을 ((E1)에 + * (정의에 의해) 동일한 (E2) 삭제 된) ...

변환 연산자를 명시하지 않고 가장 쉬운 해결 방법은 잘못된 첨자 연산자를 선언하는 것입니다 :

struct foo 
{ 
    operator char() const { return 'a'; } 
    int operator[](size_t i) const { return 1; } 

    // prevent accidental use of foo["hello"] 
    int operator[](char const*) const = delete; 
}; 
+3

... 그리고 commutativity에 의해'* (E2 + E1)'과'E2 [E1]'과 동등한가? 나는 그 것을 명백하게 부르지 않을 것입니다. –

+7

@UlrichEckhardt, 네, hello "[0]'은'0 ["hello "]'와 같습니다. – imreal

+4

실제로, 그것은 분명하지 않습니다. 그것은 C++입니다. C++ 함정과 함정들로 가득 찬 책들이 있습니다. – Jerry101

0
f["hello"]; 

은 f.operator [] (index)로 변환됩니다. 여기서 index는 "hello"를 가리키는 포인터의 값입니다. 귀하의 경우 operator [] (size_t i)를 호출합니다. 따라서 컴파일러가 불평하지 않는다는 것은 절대적으로 좋습니다.

char *c = "hello"; // c is a pointer 
f[c]; // ok 
+0

음, 이것은 완전히 잘못되어 오도 된 것입니다.'char *'는 암시 적으로'size_t'로 변환 될 수 없으므로'foo :: operator []'는 결코 선택되지 않습니다. '는''hello "[97]'와''hello"[ 'a']'와 같은''a '[ "hello"]' 게시하기 전에 수락 한 답변을 살펴보십시오. – marack