代码之家  ›  专栏  ›  技术社区  ›  Ken Y-N

boost::bind()-类似的东西,但是函数调用

  •  0
  • Ken Y-N  · 技术社区  · 6 年前

    boost::bind 或者 std:: 我可以这样做:

    int f(int a, int b)
    {
        return a + b;
    }
    
    auto f_two = boost::bind(f, 1, 1);
    

    以便 f_two() 将通过有效地调用调用 f(1, 1)

    double f_two_caller()
    {
         return f(stored_arg_1, stored_arg_2);
    }
    

    然而,我的用例是我想绑定一个前缀函数,这样我就可以说:

    auto f_print = boost::bind(printf, "Hello, world!\n");
    auto f_print_and_two = boost::bind_with_prefix(f, f_print, 1, 1);
    

    f_print_and_two() 有效执行:

    double f_print_and_two_caller()
    {
        f_print(f_print.stored_arg_1);
        return f(stored_arg_1, stored_arg_2);
    }
    

    我确信这项技术有一个合适的名称,我可以用来查找解决方案,但我现在想不起来。。。

    3 回复  |  直到 6 年前
        1
  •  1
  •   Yakk - Adam Nevraumont    6 年前
    template<class First, class Second>
    struct compose_t {
        First first;
        Second second;
        template<class...Args>
        auto operator()(Args&&...args)
        -> decltype( std::declval<Second&>()( std::declval<First&>()( std::declval<Args>()... ) ) )
        { return second(first( std::forward<Args>(args)... ) ); }
    };
    template<class First, class Second>
    compose_t<typename std::decay<First>::type, typename std::decay<Second>::type>
    compose( First&& first, Second&& second ){ return {std::forward<First>(first), std::forward<Second>(second)}; }
    

    这是功能成分。

    auto f_print = std::bind(printf, "Hello, world!\n");
    
    auto f_print_and_two = std::bind( compose(f, f_print), 1, 1 );
    
    int main() {
        f_print_and_two();
    }
    

    done .

    请注意,函数组合可以链接。你甚至可以写一个变量 compose 基于上述功能。

        2
  •  1
  •   Richard Hodges    6 年前

    #include <cstdio>
    #include <tuple>
    #include <utility>
    #include <functional>
    
    template<class F, class PrefixF, class...Args>
    auto wrap_call_prefix(F&& f, PrefixF&& pf, Args&&...args)
    {
        return [f = std::forward<F>(f), 
                pf = std::forward<PrefixF>(pf),
                args = std::make_tuple(std::forward<Args>(args)...)]
                {
                    pf();
                    return std::apply(f, args);
                };
    }
    
    int main()
    {
        auto add = [](auto x, auto y) { return x + y; };
        auto f_print = std::bind(printf, "Hello, world!\n");
    
        auto f_print_and_two_caller = wrap_call_prefix(add, f_print, 1, 2);
    
        printf("%d\n", f_print_and_two_caller());
    }
    

    std::apply 是c++17。

        3
  •  0
  •   bartop    6 年前

    如果我是你,我不会复制 bind 功能,只需这样做,非常简单:

    template<class Pre, class U>
    class with_prefix_class{
    public:
        template<class V, class W>
        with_prefix_class(V &&v, W &&w) : pre_(std::forward<V>(v)), func_(std::forward<W>(w)){}
    
        decltype(std::declval<U>()()) operator()(){
            pre_();
            return func_();
        }
    
    private:
        Pre pre_;
        U func_;
    };
    
    int f(int a, int b)
    {
        return a + b;
    }
    
    template<class Pre, class U>
    with_prefix_class<Pre, U> with_prefix(Pre &&pre, U &&u){
        return with_prefix_class<Pre, U>(std::forward<Pre>(pre), std::forward<U>(u));
    }
    
    int main(int argc, char* argv[]) {
        auto a = with_prefix([](){}, std::bind(f, 5, 3));
        a();
    }