c++ - 成员函数作为 std::function 传递给模板,绑定(bind)所有参数

标签 c++ templates

我已经开始构建权限管理库了, 基本思想是,您从文件中读取某种配置,并基于此您可以执行一个功能对象,该对象将包装“允许”和“限制”功能。

到目前为止的代码分为几个部分

我有一个权限管理器,它显示给定的“std::string”是否能够执行:

class PermissionManager {
    public:
        virtual bool canAccess(std::string resource) {return true;};
};

接下来,我有该函数的实际包装器:

template <typename FuncT>
class PermissionFunction {
private:
    FuncT m_restrict;
    FuncT m_allow;
    PermissionManager *m_pManager;
    std::string m_resource;

public:
    PermissionFunction(const PermissionFunction&) = delete;
    PermissionFunction& operator=(const PermissionFunction&) = delete;
    PermissionFunction(FuncT r, FuncT a, PermissionManager *man, std::string res)
        : m_restrict(r), m_allow(a), m_pManager(man), m_resource(res){
    }

    template<typename ...ARG>
    typename std::result_of<FuncT(ARG&&...)>::type operator()(ARG&&... args){
        if(m_pManager->canAccess(m_resource)){
            return m_allow(std::forward<ARG>(args)...);
        } else {
            return m_restrict(std::forward<ARG>(args)...);
        }
    }

};

所以,用法是这样的:

PermissionManager tpm{};
std::function<void(int)> testRestrict = [](int a){std::cout << "Restrict" << std::endl;};
std::function<void(int)> testAllow = [](int a){std::cout << "Allow" << std::endl;};
PermissionFunction<decltype(testRestrict)> testPerm(testRestrict, testAllow, &tpm, "hi");
for(int i = 0; i <10; i++){
    testPerm(i);
}

它对于非成员 std::functions 非常有用,但是当我想用成员函数定义它时,它会变得非常困惑:

class test {
    public:
        void testato(int i){
            std::cout << i << std::endl;
        }
    PermissionManager perm{};
    PermissionFunction<std::function<void(int)>>
permf{
      std::bind(&test::testato, this, std::placeholders::_1),
      std::bind(&test::testato, this, std::placeholders::_1),
      &perm, "hi"};
};

我想知道是否有任何方法可以缩短成员变量类型的使用,我也在考虑使用模板,但我不确定如何使用带有 veriadic 模板参数的 std 绑定(bind),它有适用于任何函数类型。

目标是让函数声明与给定示例中的 std::functions 类似,以便我可以用这种方式定义成员对象:

some_template<decltype(member_f)> 
wrapper_member{member_f, member_f, &tpm, "resource"} 

其中member_f是类的实际成员函数。理想情况下会推断出类型,但我认为以这种方式重复它也是可以接受的:

some_template<return_t(args_t)>
wrapper_member{member_f, member_f, &tpm, "resource"} 

最佳答案

C++20 引入 std::bind_front它将参数仅绑定(bind)到前导参数,因此不需要使用占位符对象。它可以使您的代码更加简洁。

PermissionFunction<std::function<void(int)>> permf{
  std::bind_front(&test::testato, this),
  std::bind_front(&test::testato, this),
  &perm, "hi"};

可能的 C++17 实现:

#include <tuple>
#include <utility>

template <typename F, typename... Xs>
auto bind_front(F&& f, Xs&&... xs)
{
  return [
    f = std::forward<F>(f),
    xs = std::make_tuple(std::forward<Xs>(xs)...)](auto&&... ys) -> decltype(auto)
  {
    return std::apply(
      f,
      std::tuple_cat(xs, std::forward_as_tuple(std::forward<decltype(ys)>(ys)...)));
  };
}

关于c++ - 成员函数作为 std::function 传递给模板,绑定(bind)所有参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56539908/

相关文章:

c++ - 递归 AsString() 在 C++ 中打印 STL 容器

javascript - Vuejs模板继承

c++ - 如何为函数模板编写显式特化代码(字符串的冒泡排序数组)

c++ - 基类中的私有(private)静态成员

c++ - 从 float C++ 中提取数字

c++ - xtensor:将 View 分配给 double

c++ - __time32_t 时间精度?

c++ - 无法通过Visual Studio在cpp文件中构建devlib库函数

c++ - 错误 : unitialized member with const type c++

c++ - 严重错误 -> c0000374