[英]passing member-function as argument to function-template
Consider three ways to implement a routine in c++: through functors, member functions, and non-member functions. 考虑在c ++中实现例程的三种方法:通过仿函数,成员函数和非成员函数。 For example,
例如,
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
class FOO
{
public:
void operator() (string word) // first: functor
{
cout << word << endl;
}
void m_function(string word) // second: member-function
{
cout << word << endl;
}
} FUNCTOR;
void function(string word) // third: non-member function
{
cout << word << endl;
}
Now consider a template-function to call the three functions above: 现在考虑一个模板函数来调用上面的三个函数:
template<class T>
void eval(T fun)
{
fun("Using an external function");
}
What is the proper way to call FOO::m_function
through eval? 通过eval调用
FOO::m_function
的正确方法是什么? I tried: 我试过了:
FUNCTOR("Normal call"); // OK: call to ‘void FOO::operator()(string)‘
eval(FUNCTOR); // OK: instantiation of ‘void eval(T) [with T = FOO]’
function("Normal call"); // OK: call to ‘void function(string)’
eval(function); // OK: instantiation of ‘void eval(T) [with T = void (*)(string)]’
FUNCTOR.m_function("Normal call"); // OK: call to member-function ‘FOO::m_function(string)’
eval(FUNCTOR.m_function); // ERROR: cannot convert ‘FOO::m_function’ from type
// ‘void (FOO::)(std::string) {aka void (FOO::)(string)}’
// to type ‘void (FOO::*)(std::basic_string<char>)’
// In instantiation of ‘void eval(T) [with T = void (FOO::*)(string)]’:
// ERROR: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’
A pointer to member function and a pointer to function are two different beasts. 指向成员函数的指针和指向函数的指针是两种不同的动物。 The former takes an implicit first argument, the
this
pointer, or in other words, a pointer to the instance on which the member function is to be invoked on. 前者采用隐式的第一个参数,即
this
指针,或者换句话说,指向要在其上调用成员函数的实例的指针。
Typically, in order to be able to pass the member function as a callable object, you bind
the instance on which it is to be invoked on, and then use placeholders
to indicate arguments that will be passed to the callable later. 通常,为了能够将成员函数作为可调用对象传递,您可以
bind
要在其上调用它的实例,然后使用placeholders
来指示稍后将传递给可调用对象的参数。 In your case 在你的情况下
eval(std::bind(&FOO::m_function, &FUNCTOR, std::placeholders::_1));
The first argument to bind
above is the pointer to member function that you want to invoke, and the second is a pointer to the FOO
instance on which you want to invoke m_function
. 上面
bind
的第一个参数是指向要调用的成员函数的指针,第二个是指向要调用m_function
的FOO
实例的指针。 The last one is a placeholder that indicates the first argument passed to the callable created by bind
should be used when calling the member function. 最后一个是占位符,指示在调用成员函数时应使用传递给
bind
创建的可调用对象的第一个参数。
Another way to do this is to pass a lambda expression to eval
that takes a char const *
(or std::string const&
) argument and calls the member function. 另一种方法是将lambda表达式传递给
eval
,该表达式采用char const *
(或std::string const&
)参数并调用成员函数。
eval([](char const *c) { FUNCTOR.m_function(c); });
Inside eval
, you cannot call a member function because you don't have any object; 在
eval
,你不能调用成员函数,因为你没有任何对象;
you may go for this: 你可以这样做:
template<class T, class U>
void eval(T&& object, U fun)
{
(object.*fun)("Using an external function");
}
and then 接着
eval(FUNCTOR, &FOO::m_function);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.