【问题标题】:boost::bind()-like thing, but for function callsboost::bind() 类似的东西,但用于函数调用
【发布时间】:2019-03-17 07:13:40
【问题描述】:

鉴于 boost::bindstd:: 等价物,我可以做到这一点:

int f(int a, int b)
{
    return a + b;
}

auto f_two = boost::bind(f, 1, 1);

所以f_two() 将通过有效调用一个中间函数来返回 2,该函数通过任何实现机制调用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);
}

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

【问题讨论】:

  • lambdas 会为你工作吗?
  • @HolyBlackCat 我将用c++11 重新标记,因为我可以达到那么高但不能更高,所以 lambdas 可能会起作用。注意f()不能修改,我想把最终的解决方案包装成一个mixin类之类的。
  • 最近我偶然发现了boost::hof::decorate,它看起来也可以解决问题。

标签: c++ c++11 boost function-binding


【解决方案1】:

我认为根据您的描述,这就是您要寻找的:

#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。

【讨论】:

  • 不错,但是 C++17; C++11 会好很多。请注意,还有一个boost::apply
  • [](auto x, auto y) 也是 C++14。 @KenY-N 请注意,这在 C++14 中非常简单;你确定你只会 C++11?
  • @Yakk-AdamNevraumont 该项目有很多需要调整的文件,我不确定我们的主要第 3 方库是否 100% 支持 C++14。
【解决方案2】:

如果我是你,我不会复制 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();
}

【讨论】:

    【解决方案3】:
    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函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      • 2010-11-25
      • 2023-03-30
      相关资源
      最近更新 更多