如何在pre-lambda编译器中处理lambda

How to handle lambdas in a pre-lambda compiler

本文关键字:处理 lambda 编译器 pre-lambda      更新时间:2023-10-16

我有一些代码可以通过使用lambdas大大降低复杂性。然而,不幸的是,我们必须使用不完全支持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的编译器,就可以尽可能少地改变它,从而完全消除这个问题。

你会怎么做呢?

对于没有构造函数的匿名struct的成员变量的初始化,您可以这样做:

void function() {
   type the_thing;
   struct {
      void operator()( ... ) {...}
      type & m_member;
   } callback = {the_thing};
   use_functor( callback );
}

callback中设置type &引用m_member

您可以尝试boost lambda库或boost::phoenix。它们都被设计为在没有实际lambda支持的情况下执行lambda风格的操作。因为它们是基于模板的,所以当某些错误不像预期的那样工作时,错误可能很难调试。

对woodland的答案进行扩展:

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