模板类重载std::绑定成员函数

Template class overload std::bind a member fucntion

本文关键字:绑定 函数 成员 std 重载      更新时间:2023-10-16

有人可以帮助我以正确的方式构建此源代码,我知道我会将回调声明为std::function<void(std::unique_ptr<int>&& param)>,因为这不需要副本可构造参数(std::unique_ptr),那么如果我不使用auto来推导类型,那么正确的类型是什么?

#include <functional>
#include <memory>
template <class T>
class SomeClass {
  void someFunctionCallback(float o) = 0;
};
template <>
class SomeClass<float> {
 public:
  SomeClass() = default;
  inline void someFunction() {
      // std::function<void()>
    auto callBack {
     std::move(std::bind(&SomeClass<float>::someFunctionCallback,
                         this,
                         std::unique_ptr<int>{new int(9)}))};
     useCallBack(std::move(callBack));
  }
  inline void someFunctionCallback(std::unique_ptr<int>&& param) {
  }
  inline void useCallBack(std::function<void()> &&callBack) {
//    callBack();
  }
};
int main() {
  SomeClass<float> k;
  k.someFunction();
  return 0;
}

您的代码有几个问题。首先,auto { ... }将推导出一个std::initializer_list。这不是你想要的。请改用大括号或等效的初始值设定项。

auto callBack =
 std::bind(&SomeClass<float>::someFunctionCallback,
                     this,
                     std::unique_ptr<int>{new int(9)});

其次,您的函数接受一个右值引用,但std::bind将传递一个左值。请阅读通过std::bind传递右值以获得完整的解释,但作为一种变通方法,您可以使用这个丑陋的强制转换:

using uptr = std::unique_ptr<int>;
auto callBack =
 std::bind(&SomeClass<float>::someFunctionCallback,
                     this,
                     std::bind(static_cast<uptr&&(&)(uptr&)>(std::move<uptr&>), 
                               std::unique_ptr<int>{new int(9)})
          ) ;

最后,只需将函数作为模板即可。整个想法是不必担心类型,auto无论如何都遵循模板参数推导的规则。

template <typename T>
inline void useCallBack(T callBack) {
  callBack();
}