2009-06-07 2 views
5

최근에 연산자 오버로딩/템플릿 기능을 측정하려고 시도했으며 작은 테스트로 아래 컨테이너 클래스를 만들었습니다. 이 코드는 잘 컴파일되고 MSVC 2008 (디스플레이 11)에서 올바르게 작동하지만 MinGW/GCC와 Comeau는 모두 operator+ 과부하로 질식합니다. 나는 MSVC 이상으로 그들을 신뢰하기 때문에, 내가 뭘 잘못하고 있는지 알아 내려고하고있다. 그 곳, 그래서템플릿이있는 클래스에서 이진 연산자 오버로드가 발생했습니다.

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 
Copyright 1988-2008 Comeau Computing. All rights reserved. 
MODE:strict errors C++ C++0x_extensions 

"ComeauTest.c", line 27: error: an explicit template argument list is not allowed 
      on this declaration 
    Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
      ^

1 error detected in the compilation of "ComeauTest.c". 

내가 꼬모/MingGW가 볼을 플레이하려고 노력 힘든 시간을 보내고 있습니다 :

#include <iostream> 

using namespace std; 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
    public: void setobj(T ob); 
    T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
    obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
    return obj; 
} 

template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

a.setobj(5); 
    b.setobj(6); 

Container<int> c = a + b; 

cout << c.getobj() << endl; 

    return 0; 
} 

이 꼬모가 제공하는 오류는 다음과 같습니다

코드입니다 나는 너희들을 돌린다. 내 뇌가 C++ 구문의 무게로 많이 녹아 버렸기 때문에 오랜 시간이 걸렸으므로 좀 당혹 스럽다.).

EDIT : 초기 Comeau 덤프에 나열된 (관련성이없는) lvalue 오류를 제거했습니다.

답변

5

해결책을 찾았습니다. to this forum posting. 기본적으로 함수 프로토 타입이 있어야 클래스 내에서 'friend'를 사용할 수 있지만 함수 프로토 타입을 제대로 정의하려면 클래스를 선언해야합니다. 그러므로 해결책은 상단에 함수와 클래스의 두 가지 프로토 타입 정의를하는 것입니다. 다음 코드는 세 가지 컴파일러에서 컴파일 : 당신은 그냥 일반을 전문으로하지 않는 새 템플릿을 선언하고 이후 operator+ 후 "<>는"제거해야 다음

#include <iostream> 

using namespace std; 

//added lines below 
template<typename T> class Container; 
template<typename T> Container<T> operator+ (Container<T>& lhs, Container<T>& rhs); 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
     public: void setobj(T ob); 
       T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
     obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
     return obj; 
} 

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

    a.setobj(5); 
    b.setobj(6); 

    Container<int> c = a + b; 

    cout << c.getobj() << endl; 

    return 0; 
} 
2
template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 

. 또한 적어도 g++은 친구 선언 전에 템플릿 선언을보고 싶어하므로 Container 선언 전에 이동해야합니다. 따라서 다음 순서의 선언이 작동합니다.

// forward declaration of Container<T> 
template <typename T> 
class Container; 

template <typename T> 
Container<T> operator+(Container<T>& lhs, Container<T>& rhs) 
{ ... } 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
     ... 
}; 
0

'연산자 +'는 멤버 함수가 아니며 템플릿 처리되지 않았습니다. 그것은 템플릿 연산자를 사용하는 연산자입니다. '

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
+1

나는 연산자 +가 템플릿 기능이라고 생각 하나? 컨테이너 및 컨테이너 은 두 가지 유형이므로 컴파일러는 두 가지 다른 연산자 + 함수를 생성하여 처리해야합니다. 연산자 +가 템플릿 함수라는 것을 의미하지 않습니까? –

+0

*는 * 기능 템플릿입니다. 그러나 템플리트의 정의에서 "<>"을 생략하는 것이 옳습니다. ("<>"는 함수 템플릿 *을 지정하여 *를 호출 할 때만 사용되며 동일한 이름의 템플릿이 아닌 함수가있는 경우에만 필요합니다.) –

1

나는 이것을 GCC 하에서 찍어서 약간의 변경으로 컴파일하고 실행했다. GCC를 행복하게 만들려면 두 가지 변화가있었습니다.

하나는 친구 템플릿 기능의 선언입니다. 클래스 1과는 별도의 자체 템플릿 선언이므로 컨테이너 클래스 'T'대신에 U를 사용했습니다. 또한 operator + 뒤에 <을 제거했습니다. 나는 당신이 템플릿 전문화를 작성하지 않는 한 당신이 필요하다고 생각하지 않습니다.

 template<typename U> 
     friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs); 

, 라인

임시에 대한 참조 (추가의 결과)를 저장하도록 요청하고 있기 때문에

는 GCC 비행하지 않았다

Container<int>& c = a + b; 
. 앰퍼샌드를 제거하여 결과를 저장할 장소가 생겼습니다.

앞으로 귀하의 게시물을 보았습니다. 이는 앞으로 선언문으로 인해 작동합니다. 나는 이것을 어쨌든 그들을 필요로하지 않는 대안으로 올릴 것이라고 생각한다. 물론 GCC에서만 테스트했습니다 ...

+0

다른 게시 온라인에서이 사실을 발견했습니다. 둘의 개인적인 취향 (보다 간결함). – GRB

+0

이 템플릿은 모든 템플릿 전문화에 대한 액세스 권한을 부여합니다 (따라서 연산자 + 은 컨테이너 의 비공개 정보에 액세스 할 수 있습니다). 질문자 코드는 연산자 + 에만 액세스 권한을 부여하려고합니다 (컨테이너 의 운영자 + 만 액세스 가능) –

+0

@litb : 나는 그 문제를 언급했지만 그와 같은 시나리오를 설정하는 데 어려움이 있습니다. int 오버로드가 float의 private 멤버에 액세스하는 예제 코드 스 니펫을 제공 할 수 있습니까? – GRB

1

클래스에서 직접 함수를 정의하는 것이 좋습니다. 또한 매개 변수를 const 참조로 전달해야합니다.

template <typename T> 
class Container 
{ 
public: 
    friend Container operator+ (Container const & lhs, Container const & rhs) 
    { 
     // ... 
    } 
};