【问题标题】:How to bind a member function to an object in C++14如何将成员函数绑定到 C++14 中的对象
【发布时间】:2016-05-26 09:15:44
【问题描述】:

我正在尝试将成员函数绑定到对象,同时保持参数打开。我知道我可以通过将其包装在 lambda 表达式(如 this)中来做到这一点,但我想使用 std::bind 和 std::placeholders 来做到这一点。

到目前为止,这是我所拥有的:

template <size_t _Num>
struct place_holder {};

namespace std {
  template <size_t _Num>
  struct is_placeholder<::place_holder<_Num>> : integral_constant<size_t, _Num> {};
}

namespace _binding_helper_ {
  template <size_t ... _Indices>
  std::tuple<place_holder<_Indices>...> get_placeholders(std::index_sequence<_Indices...>) {
      return std::make_tuple(place_holder<_Indices>()...);
  }
}

template <typename _Obj, typename _Func, typename ... _Args>
std::function<_Func(_Args...)> bind_function_to_object
    (_Func (_Obj::*func)(_Args...), _Obj & obj) {
    return std::bind(func, obj,
        _binding_helper_::get_placeholders(std::make_index_sequence<sizeof...(_Args)>{}));
}

创建 place_holders 的元组工作正常,但是当我在元组的元素上调用 std::is_placeholder::value 时,它​​们都是 0。如何为 _Num 的所有必需值初始化 place_holder<_num> 结构作为 std::placeholders?希望有一个简单的解决方法。任何帮助表示赞赏。谢谢!

【问题讨论】:

  • 您能否举例说明模板是如何实例化的。
  • 我很确定 is_placeholder 需要继承自 integral_constant&lt;int, N&gt;,而不是 integral_constant&lt;std::size_t, N&gt;
  • 我想你想将obj 的地址传递给std::bind 而不是obj。喜欢return std::bind(func, &amp;obj, _binding_helper_::get_placholders(std::make_index_sequence&lt;sizeof...(_Args)&gt;{}));
  • 你需要std::make_tuple(place_holder&lt;_Indices + 1&gt;()...);,占位符从1开始,而不是0
  • 另外,你的代码中非法标识符的数量是可怕的

标签: c++ c++14 member-function-pointers stdbind


【解决方案1】:

占位符的编号从1 开始,而不是从0 开始。由于我提到的原因,我认为您的static_assert 中失败的是条件std::is_placeholder&lt;place_holder&lt;0&gt;&gt;{}

另外,您将一个占位符元组传递给std::bind。相反,您应该直接传递占位符,即place_holder&lt;Is + 1&gt;{}...

template <int Num>
struct place_holder {};

namespace std 
{
    template <int Num>
    struct is_placeholder<::place_holder<Num>> : integral_constant<int, Num> {};
}

template <typename Obj, typename C, typename Func, typename... Args, int... Is>
std::function<Func(Args...)> bind_function_to_object(Func(C::*func)(Args...), Obj&& obj, std::integer_sequence<int, Is...>)
{
    return std::bind(func, std::forward<Obj>(obj), place_holder<Is + 1>{}...);
}

template <typename Obj, typename C, typename Func, typename... Args>
std::function<Func(Args...)> bind_function_to_object(Func(C::*func)(Args...), Obj&& obj)
{
    return bind_function_to_object(func, std::forward<Obj>(obj), std::make_integer_sequence<int, sizeof...(Args)>{});
}

DEMO

【讨论】:

  • 太棒了,成功了!非常感谢!有没有办法在没有额外的模板类型 C 的情况下做到这一点?有两个模板参数基本上描述相同类型的对象似乎很奇怪。
  • @geanakuch 它允许您传递基类的成员函数和派生类的实例。但如果您不喜欢它,请删除完美转发并使用左值引用,即Obj&amp; obj,然后是(Obj::*func) 等。
猜你喜欢
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-13
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
  • 2012-01-11
相关资源
最近更新 更多