c ++ 11:比较lambda表达式

时间:2014-01-24 08:51:56

标签: c++ templates c++11 lambda

想象一下有以下课程:

#include <functional>
#include <vector>

template<typename T1> class Signaler
{
public:
  typedef std::function<void (T1)> Func;

public:
  Signaler()
  {
  }

  void Call(T1 arg)
  {
    for(Int32 i = (Int32)_handlers.size() - 1; i > -1; i--)
    {
      Func handler = _handlers[i];
      handler(arg);
    }
  }

  Signaler& operator+=(Func f)
  {
    _handlers.push_back( f );
    return *this;
  }

  Signaler& operator-=(Func f)
  {
    for(auto i = _handlers.begin(); i != _handlers.end(); i++)
    {
      if ( (*i).template target<void (T1)>() == f.template target<void (T1)>() )
      {
        _handlers.erase( i );
        break;
      }
    }

    return *this;
  }

private:
  std::vector<Func> _handlers;
};

我用以下方式使用它:

Signaler Global :: Signal_SelectionChanged;

class C1
{
public:
    void Register()
    {
        Global::Signal_SelectionChanged   += [&](SelectionChangedEventArgs* e)  { this->selectionChangedEvent_cb(e); };
    }

    void Unregister()
    {
        Global::Signal_SelectionChanged   -= [&](SelectionChangedEventArgs* e)  { this->selectionChangedEvent_cb(e); };
    }

    void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {}
};

class C2
{
public:
    void Register()
    {
        Global::Signal_SelectionChanged   += [&](SelectionChangedEventArgs* e)  { this->selectionChangedEvent_cb(e); };
    }

    void Unregister()
    {
        Global::Signal_SelectionChanged   -= [&](SelectionChangedEventArgs* e)  { this->selectionChangedEvent_cb(e); };
    }

    void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {}
};

现在,我遇到的问题是当我从C2类调用'Unregister'时,它会删除'lambda'表达式的错误版本,因为'lambda'看起来很相似。

我该如何解决这个问题?

有什么想法吗?

由于

1 个答案:

答案 0 :(得分:1)

问题是您使用的std::function::target类型不是std::function中存储的对象的类型,因此返回空指针。也就是说,您需要知道std::function中存储的对象的实际类型才能调用target

即使您使用用于添加回调的lambda闭包类型调用target,这也不会有两个原因:首先,lambda闭包类型是唯一的(5.1.2p3)所以{{ 1}}和+= lambda具有不同的类型,即使它们在语法上是相同的;第二,lambda表达式的闭包类型没有定义为-=(5.1.2p3-6,19-20),所以你的代码甚至都不会编译。

从lambdas切换到operator==无济于事,因为绑定类型也没有定义为std::bind

相反,请考虑使用id来注册/取消注册回调。您也可以使用自己的函数来定义operator==,但这将是很多工作。