2013-06-05 3 views
7

람다 함수의 두 가지 다른 유형을 미리 템플릿 인수를 모른 채로 클래스 멤버로 받아 들일 수 있습니까? 이 같은 것을 할 수 있다는 것을람다가 클래스 멤버로 기능 함

struct two_functors { 
    std::function<???> a; 
    std::function<???> b; 
    ... 
}; 

같은 :

본질적으로 tuple
void main(){ 
    vector<two_functors> many_functors; 

    int a = 2; 
    int b = 3; 
    double c = 4.7; 
    double d = 8.4; 

    two_functors add_and_subtract; 
    add_and_subtract.a = [a, b](int x, int y){cout << x + y << endl;}; 
    add_and_subtract.b = [c, d](double x, double y){cout << x - y << endl;}; 

    two_functors multiply_and_divide; 
    multiply_and_divide.a = [c, d](double x, double y){cout << x * y << endl;}; 
    multiply_and_divide.b = [a, b](int x, int y){cout << x/y << endl;}; 

    many_functors.push_back(add_and_subtract); 
    many_functors.push_back(multiply_and_divide); 

    for (auto functors : many_functors){ 
     functors.a(); 
     functors.b(); 
    } 

} 
+0

는 –

+0

는'클래스 템플릿 수 two_functors' 수, 내가 기대 ... 템플릿을 사용하여 수행 할 수 있을까요? 'add_and_print.a()'와'add_and_print.b()'가'x','y','s'로 전달할 인자가없이 올바르지 않습니까? – aschepler

+0

뭔가를 미리 선언해야하는 유일한 이유는 다른 것이 뭔가를 사용하는 경우입니다. 그래서 당신은 어떤 문구에'add_and_print'를 사용하고 어떤 내용을 담고 있지 않은지 알기를 기대합니다. 당신이하려는 일의 모범이 있습니까? – aschepler

답변

3

다양한 시간에 two_functors을 구성하고 나중에 순서대로 모두 실행하려는 경우 캡처 된 데이터 만 사용할 수 있습니다.

struct two_functors 
{ 
    function<void()> a; 
    function<void()> b; 
}; 

int main() 
{ 
    vector<two_functors> many_functors; 

    int a = 2; 
    int b = 3; 
    double c = 4.7; 
    double d = 8.4; 

    two_functors add_and_subtract { 
     [a, b](){cout << a + b << endl;}, 
     [c, d](){cout << c - d << endl;} 
    }; 

    two_functors multiply_and_divide { 
     [c, d](){cout << c * d << endl;}, 
     [a, b](){cout << a/b << endl;} 
    }; 

    many_functors.push_back(add_and_subtract); 
    many_functors.push_back(multiply_and_divide); 

    for (auto functors : many_functors){ 
     functors.a(); 
     functors.b(); 
    } 
} 
+0

이것은 실제로 필요한 것입니다! 고마워, 람다에 대한 나의 초기 이해가 결함이있는 것 같다. –

2

. 인터페이스가 어떻게 구현되는지 볼 수 있습니다.

template< class F0, class F1 > 
struct two_functors { 
    F0 func0; 
    F1 func1; 
}; 

template< class F0, class F1 > 
two_functors<F0, F1> make_two_functor(F0&& f0, F1&& f1) 
{ 
    // Added [std::forward][2] 
    return two_functors<F0,F1>(std::forward<F0>(f0), std::forward<F1>(f1)); 
} 
+0

'auto f1 = [] {}; 자동 결과 = make_two_functor (f1, f1);'참조 유형의 구조체 멤버를 사용합니다. 나는 그것이 당신이 원하는 것이라고 생각하지 않습니다. – aschepler

+0

좋은 지적. 그럼 make_tuple이 어떻게 처리합니까? –

+0

'std :: make_tuple'은 반환 된 튜플에 대한 매개 변수로'std :: decay :: type'을 사용합니다. ('std :: ref'와'std :: cref'에 대한 여분의 로직을 무시합니다.) – aschepler

0

Steven의 대답에 대한 대안은 중간 "우산"클래스를 사용하는 것입니다.

편집 : 그냥 g에 대한 예제를 컴파일 ++ (GCC) 4.5.3

#include <functional> 
#include <iostream> 

using namespace std; 

class myfunction 
{ 

}; 

template <typename T> 
class specificFunction : public myfunction 
{ 
    public: 
    function<T> f; 

    specificFunction(function<T> pf) 
    { 
     f = pf; 
    } 
}; 

struct two_functors { 
    myfunction* a; 
    myfunction* b; 
}; 



int main() 
{ 
    myfunction* f = new specificFunction<void(int,int)> ([](int a, int b) { cout << a << " - " << b << endl; }); 
    myfunction* f2 = new specificFunction<void(double,int)> ([](double a, int b) { cout << a << " - " << b << endl; }); 

    two_functors tf; 
    tf.a = f; 
    tf.b = f2; 

    ((specificFunction<void(int,int)>*)(tf.a))->f(4,5); 
    ((specificFunction<void(double,int)>*)(tf.b))->f(4.02,5); 

} 
+0

'myfunction *'으로 유용하게 쓸 수있는 실용적인 방법은 없습니다. – aschepler

+0

@aschepler 당신은 무엇을 의미합니까? 구조체 대신 컨테이너에 함수를 넣는다면이를 해결할 수있는 방법 중 하나입니다. 당신의 의견을 더 설명 할 수 있습니까? – Pedrom

+0

물론 add_and_print.a = make_specificFunction ([a, b] (int x, int y) {return x + y;});'를 할 수 있습니다. 그러나 myfunction에는 operator()가 없으므로'(* add_and_print.a) (4,5);'할 수 없다. – aschepler

0

하지 대답하기 위해 (난 그냥 형식의 위업을 필요로), 스티븐의 제안의 단지 변화

template<typename A, typename B> 
two_functors<A,B> make_two_functors(A&& a, B&& b) { 
    return two_functors<A,B> {a, b}; 
} 

std::forward<T>과 비교하면 단점이 있습니까?

Btw - 어떻게 든 그런 "제조사"에 대한 필요성이 C++ 11에서 사라 졌으면 좋겠다.

+0

std :: forward없이 r-value 참조를 제대로 받아 들일 수 없으며 구조체의 기본 이동 생성자가 호출되지 않습니다. –