2011-04-19 2 views
2

코드를 Ubuntu 4.4.1 g ++ 컴파일러로 전송했습니다. 아래에 operator ++ (int)을 오버로드하는 동안 (T*)에 대해 오류가 발생하지만 (T*&)에는 정상적으로 작동합니다. 이전 버전 (linux-64에서는 정확한 버전을 기억하지 못함)에서는 (T*)도 정상적으로 작동했습니다.오류 : 연산자가 오버로드되는 동안 lvalue가 필요합니다. ++/- etc

이유가 있다면 ?

template<typename T> 
struct Wrap 
{ 
    void *p; // Actually 'p' comes from a non-template base class 
    Wrap<T>& operator ++() 
    { 
    ((T*)p) ++; // throws error; if changed to (T*&) then ok! 
    return *this; 
    } 
// ... 
}; 
int main() 
{ 
    Wrap<int> c; 
    ++c; // calling prefix increment 
} 
+0

'operator ++ (int)'를 의미 했습니까? – GManNickG

답변

2

타입 캐스트의 결과는 좌변없는, 그래서 할당하고 (내장) ++ 할당의 한 형태입니다 수 없습니다

적절한 서명은 아래를 참조하십시오. 컴파일러가 작동하면 버그가 발생했습니다.

*(T**)&p과 동일하지만 컴파일 할 때 앨리어싱 규칙 (컴파일러는 다른 유형의 포인터 (및 참조)이 동일한 객체를 가리 키지 않는다고 가정하기 때문에)이 형식적으로 유효하지 않으므로, 모든 알려진 컴파일러에서 작동하지만.

에 깨끗한 식으로 :

p = static_cast<void *>(static_cast<T *>(p) + 1) 

(++ C에서 C 스타일 캐스트를 사용하지 않습니다) 및 ++ 것과 같은 방식으로 컴파일 할 수있는 컴파일러에 의존하고 있습니다. 그러나 템플릿 인수를 사용하여 포인터를 정의 할 때 (샘플 코드에서) 올바르게 입력 된 포인터를 사용하는 것이 훨씬 낫습니다. (멤버 포인터에서도 작동 할 것이라고 말하고 싶지만 의미가 없습니다. ++).

+1

실제로, 가장 깨끗한 방법은'reinterpret_cast'가 아니라'static_cast'를 사용하는 것이고, Void 포인터 변환은' C++에서 static_cast를 호출합니다. – AnT

+0

@ AndreyT : 고마워요. 'reinterpret_cast'를'static_cast'로 변경했습니다. –

+0

'알려진 컴파일러에서 작동하지만'g ++을 제외하고는 (적어도). 컴파일러가 여러 유형의 포인터가 별명을 지정할 수 없다는 사실을 자주 사용하는 경우가 빈번합니다. (다른 타입에 대한 포인터가 다른 크기와 표현을 가질 수도 있다는 사실도 있지만 실제적인 문제보다 더 이론적 인 문제입니다.) –

1

접두사와 후행 증가 서명이 섞여있는 것처럼 보입니다. 또한, 귀하의 유형이 T임을 안다면 왜 void *를 사용합니까? http://www.codeguru.com/forum/showthread.php?t=231051

+1

문제는 주석 처리 된 행에 있으며 일반 구형 포인터에서 내장 연산자 ++를 호출하고 있습니다! (나는 당신에게 -1을 주겠지 만, 링크는 유용하지만, 주된 지점에 대답하지 않는다.) –