【问题标题】:Lambda functions as class membersLambda 函数作为类成员
【发布时间】:2013-06-05 16:41:25
【问题描述】:

是否可以在不提前知道模板参数的情况下接受两种不同类型的 lambda 函数作为类成员

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

这样的事情是可能的:

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();
    }

}

【问题讨论】:

  • 可以使用模板完成,我希望...
  • two_functors 可以作为类模板吗?如果没有一些参数作为xys 传递,add_and_print.a()add_and_print.b() 不正确吗?
  • 需要提前声明某些东西的唯一原因是其他东西是否使用它。因此,您希望某些语句使用 add_and_print 而不知道它包含什么?你有一个你想要做什么的例子吗?
  • 嵌套可能无关紧要。您可以将类模板嵌套在非模板类中。
  • 如果没有大量的包装和参数检查代码,就不可能使具有不同参数类型的函子容器有用。

标签: c++ c++11 functor lambda


【解决方案1】:

如果你只是想在不同的时间构造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();
    }
}

【讨论】:

  • 这实际上正是我所需要的!谢谢,看来我最初对 lambdas 的理解是有缺陷的。
【解决方案2】:

本质上是tuple。你可以看到这个接口是如何实现的。

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) ); 
}

【讨论】:

  • auto f1 = []{}; auto result = make_two_functor( f1, f1 ); 使用具有引用类型的结构成员。我不认为那是你想要的。
  • std::make_tuple 使用std::decay&lt;Ti&gt;::type 作为返回元组的参数。 (忽略std::refstd::cref 的额外逻辑。)
【解决方案3】:

不是试图回答(我只需要格式化功能),只是 Steven 提议的变体

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&lt;T&gt; 相比,这有什么缺点吗?

顺便说一句 - 我不知何故希望 C++11 不再需要这种“制造商”。

【讨论】:

  • 没有std::forward,它不能正确接受r-value引用,并且不会调用struct的默认移动构造函数。
【解决方案4】:

史蒂文的答案的替代方法是使用中间“伞”类。

编辑:刚刚在 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);

 }

【讨论】:

  • 当然,myfunction* 没有实用的方法来做任何有用的事情。
  • @aschepler 你是什么意思?如果您将函数而不是结构放在容器中,这是解决它的一种方法。你能进一步解释你的评论吗?
  • 当然,您可以使用add_and_print.a = make_specificFunction( [a,b](int x, int y) { return x+y; } );。但是你不能做(*add_and_print.a)(4,5);,因为myfunction没有operator()
  • @aschepler 当然可以,您只需要使用正确的签名进行转换...类似于 ((SpecificConnector*)(*add_and_print.a))。 f(4,5);
  • &lt;&gt; 之间的内容作为模板参数无效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 2018-12-11
  • 2017-10-13
  • 1970-01-01
  • 2013-08-16
  • 1970-01-01
相关资源
最近更新 更多