bind 如何知道何时转换为指针?
How does bind know when to cast to pointer?
我在 C++ 中发现了一个有趣的东西。
using namespace std;
struct Person {
string name;
bool check() {
return name == "carol";
}
};
int main()
{
Person p = { "Mark" };
list<Person> l;
l.push_back(p);
if (find_if(l.begin(), l.end(), bind(&Person::check, std::placeholders::_1)) == l.end())
{
cout << "Not found";
}
return 0;
}
上面的 if 语句可以正常工作。在取消引用迭代器 for_each 时获取对象并将其传递给函数。 bind 以某种方式知道(在绑定时)指向成员函数的指针的第一个参数应该是一个指针。但在下面的示例中,它不知道这一点,并且由于从 Person 转换为 Person* 而抛出错误。那么绑定是如何工作的呢?以及如何在下面的例子中传递一个指针?
find_if(l.begin(), l.end(), bind(mem_fun(&Person::check), std::placeholders::_1)) == l.end()
我想出了类似的方法,但我不确定这是否是最好的方法。
find_if(l.begin(), l.end(), bind([](Person& p) { return p.check(); }, std::placeholders::_1)) == l.end()
您看到的错误与 bind
无关,它是 mem_fun
's(已弃用,将在下一版本的 C++ 中删除)错误。当您使用 mem_fun
包装指向成员函数的指针时,您需要将 指针 传递给要在其上调用成员函数的实例。
find_if
将取消引用迭代器并将结果传递给它的谓词,这意味着您正在尝试将 Person&
而不是 Person*
传递给 mem_fun_t
。如果要传递引用,请改用 mem_fun_ref
。所以下面会编译
find_if(l.begin(), l.end(), bind(mem_fun_ref(&Person::check), std::placeholders::_1))
// ^^^^^^^^^^^
作为 Barry ,你甚至不需要在表达式中使用 bind
,下面的方法也行得通
find_if(l.begin(), l.end(), mem_fun_ref(&Person::check))
或者使用mem_fun
/mem_fun_ref
的C++11替换,mem_fn
find_if(l.begin(), l.end(), mem_fn(&Person::check))
最后,也可以使用lambda表达式
find_if(l.begin(), l.end(), [](Person& p) { return p.check(); })
mem_fun
不的原因是:
Creates a member function wrapper object, deducing the target type from the template arguments. The wrapper object expects a pointer to an object of type T
as the first parameter to its operator()
.
要完成同样的事情,您需要使用 std::mem_fun_ref
(不需要 bind
):
find_if(l.begin(), l.end(), std::mem_fun_ref(&Person::check))
但实际上,您应该更喜欢更通用的 std::mem_fn
,它允许两者兼顾,另外前两者将在 C++17 中弃用:
Function template std::mem_fn generates wrapper objects for pointers to members, which can store, copy, and invoke a pointer to member. Both references and pointers (including smart pointers) to an object can be used when invoking a std::mem_fn
.
std::bind
同样允许引用或指针:
As described in Callable, when invoking a pointer to non-static member function or pointer to non-static data member, the first argument has to be a reference or pointer (including, possibly, smart pointer such as std::shared_ptr
and std::unique_ptr
) to an object whose member will be accessed.
我在 C++ 中发现了一个有趣的东西。
using namespace std;
struct Person {
string name;
bool check() {
return name == "carol";
}
};
int main()
{
Person p = { "Mark" };
list<Person> l;
l.push_back(p);
if (find_if(l.begin(), l.end(), bind(&Person::check, std::placeholders::_1)) == l.end())
{
cout << "Not found";
}
return 0;
}
上面的 if 语句可以正常工作。在取消引用迭代器 for_each 时获取对象并将其传递给函数。 bind 以某种方式知道(在绑定时)指向成员函数的指针的第一个参数应该是一个指针。但在下面的示例中,它不知道这一点,并且由于从 Person 转换为 Person* 而抛出错误。那么绑定是如何工作的呢?以及如何在下面的例子中传递一个指针?
find_if(l.begin(), l.end(), bind(mem_fun(&Person::check), std::placeholders::_1)) == l.end()
我想出了类似的方法,但我不确定这是否是最好的方法。
find_if(l.begin(), l.end(), bind([](Person& p) { return p.check(); }, std::placeholders::_1)) == l.end()
您看到的错误与 bind
无关,它是 mem_fun
's(已弃用,将在下一版本的 C++ 中删除)错误。当您使用 mem_fun
包装指向成员函数的指针时,您需要将 指针 传递给要在其上调用成员函数的实例。
find_if
将取消引用迭代器并将结果传递给它的谓词,这意味着您正在尝试将 Person&
而不是 Person*
传递给 mem_fun_t
。如果要传递引用,请改用 mem_fun_ref
。所以下面会编译
find_if(l.begin(), l.end(), bind(mem_fun_ref(&Person::check), std::placeholders::_1))
// ^^^^^^^^^^^
作为 Barry bind
,下面的方法也行得通
find_if(l.begin(), l.end(), mem_fun_ref(&Person::check))
或者使用mem_fun
/mem_fun_ref
的C++11替换,mem_fn
find_if(l.begin(), l.end(), mem_fn(&Person::check))
最后,也可以使用lambda表达式
find_if(l.begin(), l.end(), [](Person& p) { return p.check(); })
mem_fun
不的原因是:
Creates a member function wrapper object, deducing the target type from the template arguments. The wrapper object expects a pointer to an object of type
T
as the first parameter to itsoperator()
.
要完成同样的事情,您需要使用 std::mem_fun_ref
(不需要 bind
):
find_if(l.begin(), l.end(), std::mem_fun_ref(&Person::check))
但实际上,您应该更喜欢更通用的 std::mem_fn
,它允许两者兼顾,另外前两者将在 C++17 中弃用:
Function template std::mem_fn generates wrapper objects for pointers to members, which can store, copy, and invoke a pointer to member. Both references and pointers (including smart pointers) to an object can be used when invoking a
std::mem_fn
.
std::bind
同样允许引用或指针:
As described in Callable, when invoking a pointer to non-static member function or pointer to non-static data member, the first argument has to be a reference or pointer (including, possibly, smart pointer such as
std::shared_ptr
andstd::unique_ptr
) to an object whose member will be accessed.