boost :: function <void(int)=“”>类型兼容性,它是如何完成的?</void>

时间:2013-09-21 01:55:44

标签: c++ boost

解释一下:

struct X
{
  void foo(int arg) { cout << "X" << arg << endl; }
};

struct Y
{
  void bar(int arg) { cout << "Y" << arg << endl; }
};

int main(int argc, char *argv[])
{
  X x;
  Y y;

  mem_fun1_t<void, X, int> f1 = std::mem_fun(&X::foo);  
  boost::function<void (int)> f11 = std::bind1st(f1, &x);
  f11(2);

  mem_fun1_t<void, Y, int> f2 = std::mem_fun(&Y::bar);
  boost::function<void (int)> f22 = std::bind1st(f2, &y);
  f22(2);

  f11 = f22;  // WOW, THIS IS ALLOWABLE
}

Boost如何在封面下工作以允许行f11 = f22?

似乎不寻常,因为f11是一个函子,其运算符(int)用x的这个调用X :: foo(int),所以它似乎是特定于X的类型,然后当我对f2 /执行相同操作时f22具体到Y,那么如何允许f11 = f22?

我实际上想要做f11 = f22行,但我很惊讶地看到这是允许的,并且我试图理解这不是类型不匹配。

我知道,“使用来源,Luke”,但Boost来源很难跟踪/理解那里发生的一切。

如果可以,为了您的答案,可以显示通过模板化扩展的类,这将有所帮助。

我当时认为它是通过虚空*铸造或类似的东西来逃避这一点,但这看起来像是一个黑客,并在Boost之下屈服于那个级别。那么whassup?

顺便说一句,如果你之前没有遇到过这种情况,你至少应该对这一点魔法感到惊讶,因为你不能说上面的“x = y”,因为它们显然是不允许的是不同的类型,没有X :: operator =(Y&amp;),所以这就是这种惊奇的来源 - 它是一个聪明的诡计。

1 个答案:

答案 0 :(得分:3)

使用的技术称为类型擦除。

我将演示一个用C ++ 11编写的玩具类。许多细节都不准确,但一般技术是:

struct nullary_impl {
  virtual void invoke() const = 0;
  virtual ~nullary_impl() {}
};
typedef std::shared_ptr<nullary_impl> nullary_pimpl;
struct nullary_func {
  nullary_pimpl pimpl;
  nullary_func() = default;
  nullary_func( nullary_func const& ) = default;
  template<typename F>
  nullary_func( F const& f );
  void operator()() const {
    pimpl->invoke();
  };
};
template<typename T>
struct nullary_impl_impl:nullary_impl {
  T t;
  virtual void invoke() const override {
    t();
  }
  nullary_impl_impl( T const& t_ ):t(t_) {}
};
template<typename F>
nullary_func::nullary_func( F const& f ):
  pimpl( std::make_shared( nullary_impl_impl<F>(f) )
{}

现在在这种情况下,该类不是模板类,但它是一个模板类并不是重要的部分。

重要的是它有一个模板构造函数。此模板构造函数根据我们构造nullary_func的类型创建自定义类型对象,然后存储指向自定义类型对象的抽象基础的指针。这个抽象基础有一个我们称之为某种类型的virtual方法。自定义子类型实现virtual方法,并在基础类型上调用()

现在,shared_ptr可能不是boost使用的(可能是某种value_ptr),而function中你有template类和template构造函数,还有很多其他细节。如果你想获得幻想,你可以实现自己的动态调度而不是virtual调用。在真正的C ++ 11中,我将完美转发所有需要的完美转发单参数构造函数的问题。