C++ 如何在初始化 std::function 时将占位符绑定到 reference/ref 参数?

C++ how can we bind a placeholder to a reference/ref argument when initializing a std::function?

#include <functional>
#include <string>

int fn( int a, int & b ) { return a+b; }

struct Fn_struct {
    std::string name {};
    // std::function<int (int,int&)> my_fn {};
    std::function<decltype(fn)> my_fn {};
};

int main()
{
    Fn_struct my_fn_struct1 {"fn(a,b)", std::function<decltype (fn)> {fn} };
    Fn_struct my_fn_struct2 {"fn(a,b)", {fn} };
    Fn_struct my_fn_struct3 {"fn(a,b)", {std::bind( fn, 1, 2) }};
    auto fn_b = std::bind( fn, 1, std::placeholders::_1 );
    Fn_struct my_fn_struct4 {"fn(a,b)", {std::bind( fn, 1, std::placeholders::_1) }};  // todo: why can't int b be a reference?
}

my_fn_struct4 没有编译,因为找不到绑定的构造函数。但是,如果 b 不是引用,它会编译。

另一方面 fn_b 编译。

如有任何解释,我们将不胜感激。

请不要问我为什么要这样做。除非完全必要,否则我宁愿不使用指针来完成此操作。

std::bind( fn, 1, std::placeholders::_1 ) returns 可转换为 std::function<int(int &)> my_fn{}; 的对象,因为传递了具有 2 个参数的函数并且第一个参数绑定到 1:

#include <functional>
#include <string>

int fn( int a, int & b ) { return a+b; }

struct Fn_struct {
    std::string name {};
    std::function<int(int &)> my_fn{};
};

int main()
{
    Fn_struct my_fn_struct4 {"fn(a,b)", {std::bind( fn, 1, std::placeholders::_1) }};
}

Fn_struct my_fn_struct3 {"fn(a,b)", {std::bind( fn, 1, 2) }};

有效因为

If some of the arguments that are supplied in the call to g() are not matched by any placeholders stored in g, the unused arguments are evaluated and discarded.

https://en.cppreference.com/w/cpp/utility/functional/bind

std::placeholders::_* 通过完美转发稍后取代它们的类型来工作。

因此,对于 std::function<int(int, int&)>std::placeholders::_1 将是右值引用,不能绑定到左值引用。

你可以使用 lambda,它在 IMO 中更清晰(即使不清楚你想要什么):

Fn_struct my_fn_struct3 {"fn(a,b)",
                         [](int/*ignored*/, int&/*ignored*/){ int b = 2; return fn(1, b); }};
Fn_struct my_fn_struct4 {"fn(a,b)",
                         [](int a, int&/*ignored*/){ return fn(1, a); }};

Demo

注意:lambda 需要额外的变量 2

恕我直言,因为别名 arg。是 2 种访问方式,因此编译器无法 and/or 阻止对没有永久引用的参数进行初始化赋值。
然后它认为这是有道理的,如果 arg.符合条件 const

#include <functional>                                                          
using namespace std;                                                            

int fn( int a, const int & b ) {            // const qualifier
  return a+b; }

struct Fn_struct {
    string name {};
    // function<int (int,int&)> my_fn {};
    function<decltype(fn)> my_fn {};
};

int main()
{
    Fn_struct my_fn_struct1 {"fn(a,b)", function<decltype (fn)> {fn} };
    Fn_struct my_fn_struct2 {"fn(a,b)", {fn} };
    Fn_struct my_fn_struct3 {"fn(a,b)", {bind( fn, 1, 2) }};
    auto fn_b = bind( fn, 1, placeholders::_1 );
      // obj names edited
    Fn_struct my_fn_struct4 {"fn(a,b)", {fn_b} }; 
    Fn_struct my_fn_struct5 {"fn(a,b)", {bind( fn, 1, placeholders::_1) }};  

}