[英]how to pass non-static member function to template argument?
For a class template with function template argument, I hope to make it a member of my class with one of my class's function as its template argument, or use a lambda to call a member function.对于带有函数模板参数的类模板,我希望以我类的一个函数作为其模板参数,使其成为我类的成员,或者使用 lambda 调用成员函数。 Here is rough example of what I want to do but I cannot get it working.
这是我想做的粗略示例,但我无法使其正常工作。
#include <iostream>
template<std::string (*fun)()>
struct wrapper{
void operator()() {std::cout<<"wrapped "<<fun()<<std::endl;}
};
std::string foo() {
return "foo";
}
struct bar{
// static function works:
static std::string str1() { return "bar1";}
wrapper<str1> wrapped_bar1;
// Non-static member function does not work:
// std::string str2() { return "bar2";}
// wrapper<&bar::str2> wrapped_bar2;
// Lambda with *this does not work either:
// static std::string str3(std::string input) { return input + "bar3";}
// wrapper<[this](){return this->str3("bar")}> wrapped_bar3;
};
int main() {
wrapper<foo> wrapped;
wrapped();
bar some_bar;
some_bar.wrapped_bar1();
}
The type of &bar::str2
is std::string (bar::*)()
and not std::string (*)()
. &bar::str2
的类型是std::string (bar::*)()
而不是std::string (*)()
。 There are ways to achieve the desired effect as shown below.有一些方法可以达到预期的效果,如下所示。 In the below shown example, i have made
wrapper
to be an ordinary class-type instead of a class template.在下面显示的示例中,我使
wrapper
成为普通的类类型而不是类模板。 Moreover, the overloaded opeartor()
is templated and is itself overloaded with a nontemplated version.此外,重载的
opeartor()
是模板化的,并且本身是用非模板化版本重载的。
struct wrapper{ //wrapper is not a class template anymore
void operator()(std::string (*fun)()) {std::cout<<"wrapped "<<fun()<<std::endl;}
template<typename T>
void operator()(std::string (T::*fun)(), T obj)
{
std::cout<<"wrapped "<<(obj.*fun)()<<std::endl;
}
};
std::string foo() {
return "foo";
}
struct bar{
// static function works:
static std::string str1() { return "bar1";}
wrapper wrapped_bar1;
std::string str2() { return "bar2";}
};
int main() {
wrapper wrapped;
wrapped(foo);
bar some_bar;
some_bar.wrapped_bar1(&bar::str1);
//------------------------------------vvvvvvvv---->pass the object also on which non-static member function should be called
some_bar.wrapped_bar1(&bar::str2, some_bar);
}
The output of the above modified program is:上述修改程序的输出为:
wrapped foo
wrapped bar1
wrapped bar2
There's no way to make something of the form wrapper<&bar::str2> wrapped_bar2;
没有办法制作
wrapper<&bar::str2> wrapped_bar2;
形式的东西。 just work as-is.按原样工作。
Consider:考虑:
struct bar {
std::string str2() { return "bar2";}
wrapper<&bar::str2> wrapped_bar2;
};
bar b1;
bar b2;
Now b1.wrapped_bar2
needs to have stored the pointer &b1
, and b2.wrapped_bar2
needs to have stored the pointer &b2
.现在
b1.wrapped_bar2
需要存储指针&b1
,并且b2.wrapped_bar2
需要存储指针&b2
。 This ( this
) pointer is the instance needed to call an instance (non-static) method.这个(
this
)指针是调用实例(非静态)方法所需的实例。
It clearly can't be part of the static type (like a free function pointer, or the member function pointer itself), because b1
and b2
have the same type but different addresses.它显然不能是静态类型的一部分(如自由函数指针或成员函数指针本身),因为
b1
和b2
具有相同的类型但地址不同。 That means you need at least to write a constructor similar to这意味着您至少需要编写一个类似于
bar::bar() : wrapped_bar2{this} {}
Now, if we're having to do this, the two wrapper
instantiations can't be used interchangeably, and we might just as well write a dedicated wrapper type for member functions:现在,如果我们不得不这样做,这两个
wrapper
实例不能互换使用,我们不妨为成员函数编写一个专用的包装器类型:
template<typename Class, std::string (Class::*fun)()>
struct mem_wrapper{
Class *instance_;
explicit mem_wrapper(Class *that) : instance_(that) {}
void operator()() {std::cout<<"wrapped "<< (instance_->*fun)() <<std::endl;}
};
If you want a single top-level type that can deal with both free functions and member functions, you need some way to hide these implementation differences (type erasure).如果你想要一个可以同时处理自由函数和成员函数的顶级类型,你需要一些方法来隐藏这些实现差异(类型擦除)。 Honestly,
std::function
already does all this for you, and it's not obvious there's a lot of benefit to reinventing this.老实说,
std::function
已经为您完成了所有这些工作,而且重新发明它有很多好处并不明显。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.