C++ C++;11绑定std::函数与存储元组和解包

C++ C++;11绑定std::函数与存储元组和解包,c++,c++11,std,variadic-templates,C++,C++11,Std,Variadic Templates,首先,我对C++11还比较陌生,所以如果我遗漏了什么,请原谅我的疏忽。所以我要做的就是让调用者传入一个函数和该函数的任意#个参数,存储它,然后稍后异步调用它。似乎有两个主要的选择: 使用std::bind将std::函数绑定到其参数(使用可变模板获得),然后稍后调用它 将参数包转换为一个元组,存储该元组和std::function,然后再次将元组解包为多个参数,并使用该参数调用函数 问题是,一种方式比另一种好吗?是否存在一种方法优于另一种方法的优点/缺点/性能优势 谢谢 编辑:根据要求,这里

首先,我对C++11还比较陌生,所以如果我遗漏了什么,请原谅我的疏忽。所以我要做的就是让调用者传入一个函数和该函数的任意#个参数,存储它,然后稍后异步调用它。似乎有两个主要的选择:

  • 使用std::bind将std::函数绑定到其参数(使用可变模板获得),然后稍后调用它
  • 将参数包转换为一个元组,存储该元组和std::function,然后再次将元组解包为多个参数,并使用该参数调用函数
问题是,一种方式比另一种好吗?是否存在一种方法优于另一种方法的优点/缺点/性能优势

谢谢


编辑:根据要求,这里有一个说明,第一种情况是更早期的绑定,在这种情况下,只要调用方传递参数,我就将参数绑定到函数,并存储绑定的func以供以后调用。第二种情况是,我分别存储func和args,并在以后需要调用函数时使用args调用函数。所以问题是哪个性能/代码大小/样式/等等更好

第三种可能是将绑定所有参数的责任转移到调用方,并且只保留一个带有要调用的签名的std::函数

例如:

struct Silly
{
    using Callback = std::function<void()>;

    void registerCallback(Callback cb) { callback_ = std::move(cb); }

    Callback callback_;
};
struct
{
使用Callback=std::函数;
void registerCallback(回调cb){Callback_u=std::move(cb);}
回调函数;
};

通过这种方式,很明显,调用方负责处理参数的生存期、值与引用语义等。

接受带有适当签名的
std::function
,然后将其存储到回调。让调用方决定如何创建/填充参数。例如:

#include <functional>
#include <iostream>

std::function<int(int)> stored_f;

void set_callback(std::function<int(int)> f) {
    stored_f = std::move(f);
}

void run_the_callback(int value) {
    std::cout << stored_f(value) << '\n';
}

int f(int i) {
    return i + 1;
}

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

int main() {
    // Plain old function pointer
    set_callback(f);
    run_the_callback(1);
    // Use std::bind
    set_callback(std::bind(g, 2, std::placeholders::_1));
    run_the_callback(2);
    // Use a lambda
    set_callback([](int i){ return f(i) * g(i, i);});
    run_the_callback(3);
}
#包括
#包括
std::存储的函数\u f;
void set_回调(std::函数f){
存储的f=std::move(f);
}
void运行\u调用(int值){

std::cout看起来像是早期的优化,我只会坚持使用更方便的方法。这个和@Nevin case可能都不适用于OP,因为延迟调用请求可能是一个场景,其中函数和参数都只在请求时提供。@pepper_chico这是一个什么问题?我专门设计了这个示例来使用两个参数在回调调用和参数时传递设置回调时存储。嗨,伙计们,谢谢你们的反馈,但我想我的问题是,就性能以及结果模板的代码大小而言,早期绑定更好还是后期绑定更好?或者差异在这里无关紧要?@user1181950我想,你应该改变你的问题,因为你在问kin只包含存储参数的延迟调用的ds。@user1181950这是您想要的更多吗?此和@Casey case可能都不适用于OP,因为延迟调用请求可能只是在请求时提供函数和参数的场景。@pepper_chico clearify?Nevin可能意味着您做了
傻事。registerCallback([=]({/*code*/})
调用方设置绑定的地方。我承认,缺少C++1y之前的
move
capture在这里有点糟糕。忘记我的观点,我只看到了将调用的责任(而不是绑定的责任)转移给调用方。
#include <functional>
#include <iostream>

template <typename Functor>
void do_stuff_and_callback_sometimes(Functor f) {
    std::cout << f(1) << '\n';
    // do some stuff, then
    std::cout << f(2) << '\n';
    // more work, and finally
    std::cout << f(3) << "\n\n";
}

int f(int i) {
    return i + 1;
}

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

int main() {
    // Plain old function pointer
    do_stuff_and_callback_sometimes(f);
    // Use std::bind
    do_stuff_and_callback_sometimes(std::bind(g, 2, std::placeholders::_1));
    // Use a lambda
    do_stuff_and_callback_sometimes([](int i){ return f(i) * g(i, i);});
}