2013-06-26 5 views
7

내가 작성한 일부 매우 복잡한 객체에 대해 기본 산술 연산자를 오버로드해야합니다. 지금까지 성공적으로 구현했습니다 operator*; 이제 operator+ 등이 필요합니다. operator*의 코드는 매우 큽니다. 그러나 operator*operator+ 사이의 유일한 차이점은 복소수에 * 대신 +을 사용하는 한 줄이됩니다. 이 라인은 여러 번 호출되는 루프 내부에있을 것이므로 효율적 이길 바란다. 이것은 함수 포인터를 암시하는 것처럼 보일 것이다. (내가 틀렸다면 수정 해주세요.)연산자를 함수 템플릿 매개 변수로 전달

이것은 템플릿을 사용하는 것처럼 보입니다. 그러나 나는 정확한 구문에 관해서는 손해보고있다. 나는 ComplicatedObject 클래스 정의 내부에서 이런 일을 생각하고 있어요 :

template <typename ComplexBinaryOp> 
ComplicatedObject BinaryOp(const ComplicatedObject& B) const { 
    // Do lots of stuff 
    for(unsigned int i=0; i<OneBazillion; ++i) { 
    // Here, the f[i] are std::complex<double>'s: 
    C.f[i] = ComplexBinaryOp(f[i], B.f[i]); 
    } 
    // Do some more stuff 
    return C; 
} 

inline ComplicatedObject operator*(const ComplicatedObject& B) const { 
    return BinaryOp<std::complex::operator*>(B); 
} 

inline ComplicatedObject operator+(const ComplicatedObject& B) const { 
    return BinaryOp<std::complex::operator+>(B); 
} 

이 질문은 관련이있다 : "function passed as template argument". 그러나 템플릿 인수로 전달 된 함수는 연산자가 아닙니다.

내가 생각할 수있는 모든 방법으로 구문을 살펴 보았지만 컴파일러는 항상 잘못된 구문을 사용합니다. 어떻게해야합니까?

편집 :

명확하게하기 위해, 나는 사람들이해야 할 수 있습니다 추가 일반화와 함께 위의 내 코드의 측면에서 완벽한 솔루션 포함 :

template <typename ComplexBinaryOp> 
ComplicatedObject BinaryOp(const ComplicatedObject& B) const { 
    // Do lots of stuff 
    for(unsigned int i=0; i<OneBazillion; ++i) { 
    // Here, the f[i] are std::complex<double>'s: 
    C.f[i] = ComplexBinaryOp()(f[i], B.f[i]); // Note extra()'s 
    } 
    // Do some more stuff 
    return C; 
} 

inline ComplicatedObject operator+(const ComplicatedObject& B) const { 
    return BinaryOp<std::plus<std::complex<double> > >(B); 
} 

inline ComplicatedObject operator-(const ComplicatedObject& B) const { 
    return BinaryOp<std::minus<std::complex<double> > >(B); 
} 

inline ComplicatedObject operator*(const ComplicatedObject& B) const { 
    return BinaryOp<std::multiplies<std::complex<double> > >(B); 
} 

inline ComplicatedObject operator/(const ComplicatedObject& B) const { 
    return BinaryOp<std::divides<std::complex<double> > >(B); 
} 
+1

'std :: complex'는 클래스 템플릿이므로'std :: complex '이 필요합니다. 하지만 그때도'complex :: operator *'와'complex :: operator +'는 * 멤버 함수 *입니다. 조작하려면'complex '인스턴스를 사용하지 않고 전달할 수 없습니다. – Praetorian

+0

게시 오류가 발생했습니다. 흥미로운 질문에 대해서는 –

+1

+1. 또한이 질문 - 관련성이 높고 흥미로운 [연산자에 대한 C++ 포인터] (http://stackoverflow.com/questions/4176895/c-pointers-to-operators)를 발견했습니다. – keelar

답변

4
내가 std::plus<std::complex> 생각

std::multiplies<std::complex>은 '당신이 무엇을하다 다시 찾고 있지만 100 % 확신 할 수는 없습니다. 귀하의 질문을 이해할 수는 없습니다. (귀하가 우리에게 보여주지 않는 코드 스 니펫입니까?)

+0

+1, 이것이 OP도 찾고있는 것 같지만 플러스 > 및 multiplies > – Praetorian

+0

@Praetorian : 그래서'plus'와'multiplies'를 사용할 수 있습니다. 'std' 스코프를 지정하지 않고? – keelar

+0

+1 네, 이것은 제가 원하는 것 같습니다, 괜찮습니다 (@Praetorian이 맞지만). 그러나 나는이 기능들을 사용하는 방법을 이해할 수 없다. 컴파일러는'ComplexBinaryOp (f [i], B.f [i])'행에 객체를 지정합니다. 그것에 대한 도움이 필요하십니까? – Mike

1

두 가지 옵션이 있습니다.

#include <functional> 

template <typename ComplexBinaryOp> 
ComplicatedObject BinaryOp(const ComplicatedObject& B, ComplexBinaryOp op) const { 
    // ... 
    C.f[i] = op(f[i], B.f[i]); 
    // ... 
} 

// functor wrapping member function pointer 
BinaryOp(B, std::mem_fn(&std::complex<double>::operator+)); 

// standard-issue functor 
BinaryOp(B, std::plus<std::complex<double>>()); 

또는 컴파일시에 전달할 : 런타임에 기능을 전달

// or another floating-point type 
typedef double (*ComplexBinaryOp)(double, double); 

template <ComplexBinaryOp op> 
ComplicatedObject BinaryOp(const ComplicatedObject& B) const { 
    // ... 
    C.f[i] = op(f[i], B.f[i]); 
    // ... 
} 

// non-member function 
template<class T> 
std::complex<T> add_complex(const std::complex<T>& a, const std::complex<T>& b) { 
    return a + b; 
} 

// non-member function pointer 
BinaryOp<add_complex<double>>(B); 

을 당신이 ComplexBinaryOp의 정의를 변경하여뿐만 아니라 멤버 함수 포인터와 동일한 기능을 수행 할 수 있다고 생각합니다.

+0

이것은 유용한 가능성처럼 보입니다. 나는 물건을 시험해보고, 당신에게 돌아갈 것이다. 감사! – Mike

+0

원래의 구문은'std :: complex :: operator *'를'std :: multiplies' 등으로 대체 한 후에도 훌륭하게 작동합니다. 또한 당신도 작동하지만, 덜 간단하다고 생각합니다. – Mike

+1

@Mike : 네, 그게 효과가 있습니다. 실제로 펑터 인스턴스를 얻기 위해서는'ComplexBinaryOp() (foo, bar)'를 써야한다. 첫 번째 예와 마찬가지로 내부 또는 외부에서 수행 할 수 있습니다. –

관련 문제