绑定到可变参数成员函数

依斯达醇

因此,情况如下:我有两个通过CRTP进行静态继承的类。基类有一个run方法,该方法使用可变参数模板调用派生方法,以便参数灵活。现在,派生类包含一个函数对象。派生类具有基类调用的实现。似乎没有必要,但是在此代码的完整版本中,运行的命令不仅仅是所包含的函数。接下来是一个方法,该方法通过将所有可变参数和实例绑定到method来将函数转换为bool(void)函数CrtpBase::Run这是我遇到的问题。我尝试了两种不同的方法,使用lambda的版本已被注释掉。两种方法均无效。我的目标是VoidFunction绑定所有参数,以便我可以在没有参数的情况下随意执行该函数。我在这里做错了什么?

#include <functional>
#include <utility>

template <typename D>
struct CrtpBase {
  template <typename ... Args>
  bool Run(Args&& ... args) const {
    return static_cast<D&>(*this).Impl(std::forward<Args>(args) ...);
  }
};

template <typename ... Args>
struct CrtpDerived : public CrtpBase<CrtpDerived<Args ...>> {
  CrtpDerived(std::function<bool(Args ...)> function) : runable(std::move(function)) {}

  bool Impl(Args&& ... args) const {
    return this->runable(std::forward<Args>(args) ...);
  }

  std::function<bool(Args ...)> runable;
};

template <typename D, typename ... Args>
std::function<bool()> VoidFunction(CrtpBase<D> base, Args&& ... args) {
//  return [&base, &args ...]()->bool{return CrtpBase<D>::template Run<Args ...>(base);};
  return std::bind(CrtpBase<D>::template Run<Args ...>, base, std::forward<Args>(args) ...);
}

int main(int argc, char** argv) {
  std::function<bool(int&)> fn = [](int& a)->bool{a /= 2; return (a % 2) == 1;};
  CrtpDerived<int&> derived(fn);
  int x = 7;
  auto voided = VoidFunction(derived, x);
  bool out = voided();
  if ((x == 3) and (out == true)) {
    return EXIT_SUCCESS;
  } else {
    return EXIT_FAILURE;
  }
}

编辑:

  1. 最终测试中的固定错别字(out == false)成为(out == true)
蚂蚁

首先,从编译器的角度来看,CrtpBase<D>::template Run<Args ...>是令牌的荒谬/不完整的组合。C ++中没有这样的表达式语法。这看起来像是尝试形成一个指向成员的指针,但是这需要显式应用&操作符

return std::bind(&CrtpBase<D>::template Run<Args ...>, base, std::forward<Args> (args) ...);

其次,这个演员

static_cast<D&>(*this)

将试图抛弃常数。不允许这样做static_cast

第三,你的

std::bind(&CrtpBase<D>::template Run<Args ...>, base, std::forward<Args> (args) ...);

将隐含 this 参数绑定 到函数参数 base 这将不起作用,因为 base 将在 VoidFunction 退出时(或在调用表达式结束时)立即 销毁 正如@aschepler在注释中正确指出的那样,将原始对象base作为CrtpBase<D>值切入CrtpDerived<int&>通过引用将其传递,然后&base用作的参数std::bind

第四,std::bind 不会“按引用”绑定,也std::forward不会对此有所帮助。这意味着a您的lambda内部fn将不会受到约束x用于std::ref解决该限制。

#include <functional>
#include <utility>

template <typename D>
struct CrtpBase {
  template <typename ... Args>
  bool Run(Args&& ... args) const {
    return static_cast<const D&>(*this).Impl(std::forward<Args>(args) ...);
  }
};

template <typename ... Args>
struct CrtpDerived : public CrtpBase<CrtpDerived<Args ...>> {
  CrtpDerived(std::function<bool(Args ...)> function) : runable(std::move(function)) {}

  bool Impl(Args&& ... args) const {
    return this->runable(std::forward<Args>(args) ...);
  }

  std::function<bool(Args ...)> runable;
};

template <typename D, typename ... Args>
std::function<bool()> VoidFunction(CrtpBase<D> &base, Args&& ... args) {
  return std::bind(&CrtpBase<D>::template Run<Args ...>, &base, std::forward<Args>(args) ...);
}

int main(int argc, char** argv) {
  std::function<bool(int&)> fn = [](int& a)->bool { a /= 2; return (a % 2) == 1; };
  CrtpDerived<int&> derived(fn);
  int x = 7;
  auto voided = VoidFunction(derived, std::ref(x));
  bool out = voided();
  if ((x == 3) && (out == false)) {
    return EXIT_SUCCESS;
  } else {
    return EXIT_FAILURE;
  }
}

最后一两件事:我不明白为什么你希望你outfalse在年底。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章