2016-09-21 2 views
2

여러 인수를 취하는 함수를 단 하나의 인수 (다른 인수의 값 제공)로 변환하는 랩퍼가 있습니다. 지금은 예를 들어, 할 수 있도록오브젝트의 함수 연산자의 인수 유형 검색

template <class R, class F, class A0, class A1> 
class CMyWrapper { 
    F m_f; 
    A0 m_default_a0; 

public: 
    CMyWrapper(F f, const A0 &default_a0) 
     :m_f(f), m_default_a0(default_a0) 
    {} 

    R operator()(const A1 &a1) const 
    { 
     return m_f(m_default_a0, a1); 
    } 
}; 

template <class R, class A0, class A1> 
CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1> 
    SupplyConstArg(R (*fun)(const A0&, const A1&), const A0 &default_a0) 
{ 
    return CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1>(fun, default_a0); 
} 

double MyFunc(const double &x, const double &y); // some function 

:이 코드는 기능와 함께 작동 SupplyConstArg(MyFunc, 1.23)(4.56)MyFunc(1.23, 4.56)을 호출합니다 (이 표현식의 왼쪽 부분은 첫 번째 인수를 계속 제공하는 함수 객체입니다). 여태까지는 그런대로 잘됐다.

는 그러나, 나는 기능을 위해 일하고 유사한 기능을 서면으로 어려움 (나는 가능한 성능 향상을 위해 함수 포인터를 피하기 위해 같은 것) 기능보다는 개체를 가지고있다. 가정 :

struct CMyFunObj { 
    double operator()(const double &x, const double &y); 
}; 

내 문제는 내가 같은 함수 객체의 인스턴스 주어진 반환 형식 또는 인수의 유형을 일치 어떻게 입니까? 지금까지 나는 다음과 같이 생각해 냈습니다.

template <class F, class R, class A0, class A1> 
R Infer(F f, R (F::*fun)(const A0 &a0, const A1 &a1) = &F::operator()); 

두 번째 인수가 지정된 경우에만.

Infer(CMyFunObj(), &CMyFunObj::operator()); 

두 번째 인수를 생략하고 기본값을 사용하면 안됩니다. 어떤 아이디어를 C++ 03에서 어떻게 할 것인가?

+1

std :: bind의 일부를 다시 구현하려는 것 같습니다.C++ 03에서는이 부분이 std :: bind1st에 의해 제공됩니다. –

+0

@ n.m. 그래, 나는 이것이 비슷하다는 것을 알고있다. 내 유스 케이스에서는 상수 인수가 항상 첫 번째가 아니므로 반환 된 함수 객체의 함수 연산자에 지정된 "가변 인수"의 색인을 지정하는 몇 가지 기능이 필요합니다. 이 부분을 이미 수행 할 수 있습니다. 함수 객체에 대한 유형 유추로 막 붙어 있습니다. 'std :: bind'에 대해서도 같은 일을 할 수 있을지 확신 할 수 없습니다. –

답변

2

, 당신은 할 수 없습니다 (당신이 typeof처럼 사용하지 않으려면) 당신이 실제로 그것을 제공 할 수 있도록 정말 그런 유형을 추론 :

struct CMyFunObj { 
    typedef double result_type; 
    double operator()(const double &x, const double &y); 
}; 

을 그리고 지금 당신은 정보의 추가 비트를 사용할 수 있습니다

template <class F, class A0> 
CMyWrapper<typename F::result_type, F, A0> 
SupplyConstArg(F f, A0 const& a0) { 
    return CMyWrapper<typename F::result_type, F, A0>(f, a0); 
} 

SupplyConstArg(CMyFunObj(), 4.0)(5.0); 

당신 형식이 A1CMyWrapper에 필요하지 않으며 템플릿 인수가 operator() 일 수 있습니다.

+0

어,'typeof'로 터벅 터벅 걷다가, 미안 해요, 구현되지 않았습니다 : mangling typeof, 대신 decltype을 사용합니다. 참으로 할 수없는 것처럼 보입니다. –

1

나는이 질문에 대한 확신이 없지만 아마도 이런 말을 할 수 있을까요?

struct X {}; 
struct Y {}; 

template <class R, class A0, class A1, class F, R(F::*)(const A0 &, const A1 &) = &F::operator()> 
void Infer(F f) { } 

struct S { 
    void operator()(const X &, const Y &) { } 
    void foo(const X &, const Y &) { } 
}; 

int main() { 
    Infer<void, X, Y>(S{}); 
    Infer<void, X, Y, S, &S::foo>(S{}); 
} 

의견에서,이는 C++ 03에서 작동합니다 :

struct X {}; 
struct Y {}; 

template <class R, class A0, class A1, class F> 
void Infer(F f, R(F::*ptr)(const A0 &, const A1 &)) { (f.*ptr)(A0(), A1()); } 

template<class F> 
void Infer(F f) { 
    Infer(f, &F::operator()); 
} 

struct S { 
    void operator()(const X &, const Y &) { } 
    void foo(const int &, const char &) { } 
}; 

int main() { 
    Infer(S()); 
    Infer(S(), &S::foo); 
} 

이렇게하면 메소드가 호출 될 지정하거나 명시 적으로 밀어 중간 기능에 의존 할 수 있습니다 인수로서.

+0

Ooopsy 정확히 똑같은 기능을하고 싶었지만 분명히 C++이 필요했습니다. 11 –

+0

이 기능은 작동하지만 사용하기 어려워 보입니다. 나는'Infer'가 호출자가 그들을 써야하는 대신 자동으로 타입을 추론하고 싶습니다. –

+0

@ theswine 당신은 C++ 03 접근이 필요합니까? –

1

당신은 단순히 중간 기능을 사용할 수 있습니다 : 당신이 유형을 추론해야 할 경우 as Barry says을 할 수

template <class F, class R, class A0, class A1> 
void Infer(F f, R (F::*fun)(const A0 &a0, const A1 &a1)); 

template <class F> 
void Infer(F f) { 
    Infer(f, &F::operator()); 
} 

Infer(CMyFunObj()); 

을, 당신이 당신의 펑터를 수정하지 않으려는 경우, 외부 헬퍼 클래스를 사용할 수 있습니다 :

template <class U> 
struct result_type; 

template <typename F> 
typename result_type<F>::type Infer(F f) { 
    return Infer(f, &F::operator()); 
} 

그리고 나중에 : C++ 03에서

struct CMyFunObj { 
    double operator()(const double& x, const double& y) { return x + y; } 
}; 

template <> 
struct result_type<CMyFunObj> { 
    typedef double type; 
}; 
+0

맞아, 나는 그 예제를 지나치게 단순화 한 것을 본다. 'Infer'가'F :: operator()'와 같은 타입을 반환 할 필요가 있다고 가정하면, 어떻게 그것을 외부 함수로 가져갈 수 있습니까? 그것은 내부에서 그것을 얻는 것이 쉽다. –

+0

@ theswine 내가 원하는 것을 할 수있는 방법이 있는지 나는 모른다. (Barry에 의하면 그렇지 않다.) 배리처럼 할 수 있지만 펑터를 수정하지 않고 답변을 업데이트했습니다. – Holt