代码之家  ›  专栏  ›  技术社区  ›  Francis Cugler

简化存储在类的std::vector成员中std::函数的使用

  •  0
  • Francis Cugler  · 技术社区  · 7 年前

    我写了这个基本类来存储 std::function<T> 在内部 std::vector<T> 我有两个免费的函数模板 foo() bar() void 然后拿一个 标准::矢量<T> 作为他们的参数。为了简单起见,他们现在做的是完全相同的;但是为了将来的参考,他们将做不同的计算或任务。到目前为止,这就是我所想到的:

    #include <vector>
    #include <functional
    #include <iostream>
    #include <exception>
    
    template<typename T>
    class MyClass {
    private:
        std::vector<std::function<void(std::vector<T>)>> myFuncs_;    
    public:
        MyClass() = default;
    
        void addFunc( std::function<void(std::vector<T>)> func ) {
            myFuncs_.push_back(func);
        }
    
        std::function<void(std::vector<T>)> caller(unsigned idx) {
            return myFuncs_.at(idx);
        }
    };
    
    template<typename T>
    void foo(std::vector<T> data) {
        std::cout << "foo() called:\n";
    
        for (auto& d : data) 
            std::cout << d << " ";
        std::cout << '\n';
    }
    
    template<typename T>
    void bar(std::vector<T> data) {
        std::cout << "bar() called:\n";
    
        for (auto& d : data)
            std::cout << d << " ";
        std::cout << '\n';
    } 
    
    int main() {
        try {
            MyClass<int> myClass;
            std::vector<int> a{ 1,3,5,7,9 };
            std::vector<int> b{ 2,4,6,8,10 };
    
            std::function<void(std::vector<int>)> funcA = std::bind(foo<int>, a);
            std::function<void(std::vector<int>)> funcB = std::bind(bar<int>, b);
            myClass.addFunc( funcA );
            myClass.addFunc( funcB );
    
            myClass.caller(0)(a);
            myClass.caller(1)(b);       
    
        } catch( std::runtime_error& e ) {
            std::cerr << e.what() << std::endl;
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;    
    }  
    

    foo() called:
    1 3 5 7 9
    bar() called:
    2 4 6 8 10
    

    下面是我想知道的:是否有任何方法可以简化这段代码;有些语法看起来是多余的,例如:在我实例化了类模板的一个实例并创建了 std::vector std::函数<T> 使用 std::bind 用我想添加到类向量的函数。然后在绑定它们并将它们添加到类的容器中之后,在这里我调用类的函数来索引要使用的函数 std::functions operator() 标准::矢量<T> 看来我是通过了这个 vector<T>

    // std::vector<T> being passed to std::bind
    std::function<void(std::vector<int>)> funcA = std::bind(foo<int>,a);
    myClass.addFunc( funcA );
    myClass.caller(0)(a);  // Again std::vector<T> being passed but to `std::function`'s operator because the stored function requires this parameter. 
    

    这是可以简化的,还是仅仅在语义上 std::function 标准::绑定 工作?如果这可以简化,是在类本身中完成以使用户更容易,还是在用户端完成?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Jans    7 年前

    std::bind 错误的方式,例如

    std::function<void(std::vector<int>)> funcA = std::bind(foo<int>, a);
    

    你已经约束了这个论点 a foo<int> funcA 不会生效,以上等同于

    std::function<void()> funcA = std::bind(foo<int>, a);
    

    为了简化代码,如果你想坚持 标准::绑定 MyClass 所有注册的 std::function

    template<typename T>
    class MyClass {
    private:
        std::vector<std::function<void()>> myFuncs_;
    public:
        MyClass() = default;
    
        template <class... F, std::enable_if_t<(sizeof...(F) > 0), bool> = true>
        void addFunc(F&&... func) {
            ((myFuncs_.push_back(std::forward<F>(func))), ...);
        }
    
        void operator()() const {
            for (auto& fn : myFuncs_) {
                fn();
            }
        }
    };
    
    
    auto funcA = std::bind(foo<int>, a);
    auto funcB = std::bind(bar<int>, b);
    myClass.addFunc(funcA, funcB);
    myClass();
    

    使用同样的方法,你可以随时切换到lambdas。

    推荐文章