如何在没有lambda的编译器中处理lambda函数

5

我有一些代码,如果使用lambda表达式可以大大降低复杂度。然而,不幸的是我们必须使用一个不完全支持C++11的编译器,而且我们不能轻易地切换。现在的问题是如何尽可能保持逻辑与lambda表达式的接近,但又没有可用的特性(即std::function可用,但lambda表达式不可用)。

通常的解决方案是在其他地方定义函数对象,然后在适当的位置使用它:

struct functor{
   functor( type & member ) : m_member( member ) {}
   void operator()( ... ) {...}
   type & m_member;
};

void function() {
   use_functor( functor(...) );
}

虽然我不太喜欢这种模式,但我已经习惯了。通常不定义类的主要原因是,我将在STL中使用函数对象,而模板不喜欢在函数内联定义结构体。但是,在我的情况下,use_functor()函数将是一个普通方法,因此我可以在函数内部定义函数对象(每个函数对象仅在一个函数内使用)。

void function() {
   struct functor{
      functor( type & member ) : m_member( member ) {}
      void operator()( ... ) {...}
      type & m_member;
   };
   use_functor( functor(...) );
}

这似乎有所改善,但仍需要更多的丑陋代码,我不喜欢。例如,我想彻底摆脱函数对象名称。如果我只使用一个值,我知道可以创建匿名结构体。

void function() {
   struct{
      // functor( type member ) : m_member( member ) {}
      void operator()( ... ) {...}
      // type & m_member;
   } callback ;
   use_functor( callback );
}

然而,目前我对于如何提供必要的数据成员毫无头绪。由于这个结构体是匿名的,所以它没有构造函数。虽然它是公共的,我可以轻松地设置成员,但这将再次添加一行代码,而我不喜欢这样。目标是在我们切换到具有干净 Lambda 的编译器后尽可能少地更改状态,从而消除这个问题。
你会如何处理这个问题?

正如我刚刚发现的那样,一些较旧的GCC甚至不能很好地处理从嵌套在函数中的结构体转换为std::function<>,并且不会喜欢任何解决方案。因此,我被迫使用选项一并分离逻辑。 - LiKao
3个回答

1
关于匿名struct成员变量的初始化,如果没有构造函数,您可以这样做:
void function() {
   type the_thing;
   struct {
      void operator()( ... ) {...}
      type & m_member;
   } callback = {the_thing};
   use_functor( callback );
}

callback 中设置 type & 引用 m_member


0

在awoodland的回答基础上进行扩展:

#define MY_LAMBDA(name, memberType, memberValue, body) \
    struct {                                     \
        void operator()( ... ) body              \
        memberType & memberValue;                   \
    } name = {memberValue}

void function() {
    type thing_to_capture;

    MY_LAMBDA(callback, type, thing_to_capture
    {
        std::cout << thing_to_capture << std::endl;
    });

    use_functor( callback );
}

您可以在任何定义结构的地方使用MY_LAMBDA。不幸的是,没有可变参数宏,您必须将所有捕获的对象包装成一个单独的对象,并且必须在“lambda声明”中指定该对象的类型。

还要注意,使用lambda表达式的等效方式为:

void function() {
    type thing_to_capture;

    auto callback = [&thing_to_capture]()
    {
        std::cout << thing_to_capture << std::endl;
    };

    use_functor( callback );
}

为了消除打字错误的可能性,您可以在宏的顶部添加 type thing_to_capture;(如果您没有调用显式构造函数或复制赋值,就像这个例子一样)。 - Richard
1
如果不能指定operator()的定义,那么MY_LAMBDA有什么用处呢? - ildjarn

0
你可以尝试使用boost lambda库或者boost::phoenix。它们都是为了实现lambda风格的操作而设计的,而且并不需要真正的lambda支持。由于它们基于模板,所以在出现意外情况导致某些功能无法正常工作时,调试可能会比较困难。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接