2009-10-26 4 views
4

는 어떻게 든 하나에 이와 같은 템플릿을 병합 할 모든 코드가 동일, "+"실제 제외 (도난, 사업부 등의 동일한 코드 뒤에)산술 연산자를 템플릿에 전달하는 방법은 무엇입니까?

template <class Result, class T1, class T2> 
class StupidAdd 
{ 
public: 
    T1 _a; T2 _b; 
    StupidAdd(T1 a, T2 b):_a(a),_b(b) {} 
    Result operator()() { return _a+_b; } 
}; 

template <class Result, class T1, class T2> 
class StupidSub 
{ 
public: 
    T1 _a; T2 _b; 
    StupidSub(T1 a, T2 b):_a(a),_b(b) {} 
    Result operator()() { return _a-_b; } 
}; 

, "-"(그리고 "StupidAdd", "StupidSub"등).

다음이 바보 같은 "펑터"는 다른 템플릿에서 사용됩니다. 프리 프로세서없이 반복을 피하는 방법은 무엇입니까? (내가 템플릿에 들어간 이유는 전 처리기를 피하는 것이 었습니다)

즉, 어떻게 산술 연산자를 템플릿에 전달할 수 있습니까?

+0

이러한 연산자에 과부하를 주려고 했습니까? 아니면이 예제입니까? – Jacob

+0

나는 산술 연산자를 오버로딩하지 않을 것이다. 단지 템플릿처럼 그들을 전달할 수 있기를 원한다. 템플릿 <클래스 결과, 클래스 A, 클래스 B, 클래스 ArithOp> 결과 DoWork (A a, B b) {return ArithOp (a, b); } StupidAdd, StupidSub와 같은 어리석은 것들을 정의하지 않고 ... – OldCoder

답변

7

아마도 std::plus<T>, std::minus<T>, std::multiplies<T>std::divides<T>을 사용할 수 있습니다. 그러나 두 피연산자가 같은 유형 인 경우 또는 왼쪽 피연산자가 첫 번째 피연산자 유형으로 변환 될 수있는 경우에만 작동합니다.

전처리기를 사용하는 경우를 제외하고는 수행하려는 작업을 수행 할 방법이 없습니다. 매크로를 원하지 않는 이유는 무엇입니까?

당신이 확인하려면 반드시 반환 형식은 결과,이 길을 따라 뭔가를 할 수 포함하기에 충분히 큰 : 여기

#include <functional> 
#include <boost/mpl/if_.hpp> 

// Metafunction returning the largest type between T and U 
// Might already exist in Boost but I can't find it right now...maybe 
// boost::math::tools::promote_args 
template <typename T, typename U> 
struct largest : 
    boost::mpl::if_< 
     boost::mpl::bool_<(sizeof(T) > sizeof(U))>, 
     T, 
     U 
    > 
{}; 

template <typename T, typename U, template <typename S> class Op> 
struct Foo 
{ 
    typedef typename largest<T, U>::type largeType; 

    largeType bar(const T & t, const U & u) 
    { 
     return Op<largeType>()(t, u); // Applies operator+ 
    } 
}; 

int main() 
{ 
    Foo<int, double, std::plus> f; 
    double d = f.bar(12, 13.0); // takes int and double, returns double 
} 

, 내가 largest metafunction를 작성하는 Boost MPL를 사용하지만, 당신은 할 수 Boost (두 가지 유형과 bool로 매개 변수화 된 클래스 템플릿, true 및 false에 대해 특수화 된)를 사용할 수없는 경우 자신의 if 메타 기능을 작성하십시오.

표현식의 반환 유형을 확인하려면 boost::result_of을 볼 수도 있습니다. 정확하게 이해하면 C++ 0x의 다음 decltype 연산자와 동일합니다.

+0

나는 할 수 없다 - 나는 연산자 + (int, double)가 double을 반환한다는 사실에 의존하고있다. std :: plus는 두 인수가 모두 같은 형식이어야합니다. – OldCoder

+0

"cpp"를 싫어하는 나의 기본적인 이유는 디버깅이 살아남은 지옥을 만드는 것입니다. 매크로를 사용하기 시작하면 gdb에서 단계별로 수행 할 수있는 능력을 잃어 버리는 순간입니다. – OldCoder

+0

방금 ​​편집 중이었습니다. 이 사실을 반영하십시오 :). 그런데, 나는 이것을하는 어떤 방법을 보지 못한다. 내가 의심하는 내장 연산자의 주소를 가져올 수없는 한. –

3

감사합니다. Luc, 매우 멋지다.

#include <functional> 

template < 
    class Result, 
    class T1, 
    class T2, 
    template <class ReturnType> class BinaryOp> 
class Stupido 
{ 
public: 
    T1 _a; T2 _b; 
    Stupido(T1 a, T2 b):_a(a),_b(b) {} 
    Result operator()() { return BinaryOp<Result>()((Result)_a,(Result)_b); } 
}; 

을 그리고 "플러스", "마이너스"인스턴스의 바보를 사용 : 드디어 간단한 방법으로 그것을했다. "결과"에 대한 캐스트가 내 필요에 충분했다. (int + double => double + double => double)

0

나는 C++ 0x decltype과 auto의 새로운 정의를 사용한다. 클래스를 정의 할 필요가 있지만이를 사용하여 클래스를 정의 할 수 있습니다. 그들은 여전히 ​​많은 작업을 정의 할 것이지만 적어도 을 사용하면을 사용하면 상당히 깨끗합니다. 특히 decltype/auto를 사용하면 명시 적으로 지정하지 않아도 올바른 반환 유형을 추론 할 수 있습니다.

인텔 C++, g ++, 코모, VC++ 2010 베타 버전, 그리고 가장 최근의 볼랜드/인스 프리트/엠바 카데로 반복 버전/이번 주 새 이름이 포함되어 있습니다.

3

내가 OldCoder의 솔루션에 대한 개선 있다고 생각 : 그것은 그래서

Stupido<int, std::plus > stup; 
int result = stup(3.0f, 2.0); 

과 같은 기능의 오브젝트가 복수의 피연산자로 사용할 수 있습니다

#include <functional> 

template <class Result, 
      template <class Result> class BinaryOp> 
struct Stupido 
{ 
    template <typename T1, typename T2> 
    Result operator()(const T1& a, const T2& b) { return BinaryOp<Result>()((Result)a,(Result)b); } 
}; 

이 방법으로 호출은 다음과 같이 할 수는 std::transform 전화로 전달 될 수 있습니다.

템플릿 선언에서 하나의 결과를 제거하는 방법이 있어야한다고 생각합니다. 그러나 찾을 수 없습니다.

+3

template class BinaryOp> 구조체 Stupido {...}; –

관련 문제