![](/img/trans.png)
[英]How to pass non-static member function as template argument to another member function?
[英]how to pass non-static member function to template argument?
對於帶有函數模板參數的類模板,我希望以我類的一個函數作為其模板參數,使其成為我類的成員,或者使用 lambda 調用成員函數。 這是我想做的粗略示例,但我無法使其正常工作。
#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();
}
&bar::str2
的類型是std::string (bar::*)()
而不是std::string (*)()
。 有一些方法可以達到預期的效果,如下所示。 在下面顯示的示例中,我使wrapper
成為普通的類類型而不是類模板。 此外,重載的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);
}
上述修改程序的輸出為:
wrapped foo
wrapped bar1
wrapped bar2
沒有辦法制作wrapper<&bar::str2> wrapped_bar2;
形式的東西。 按原樣工作。
考慮:
struct bar {
std::string str2() { return "bar2";}
wrapper<&bar::str2> wrapped_bar2;
};
bar b1;
bar b2;
現在b1.wrapped_bar2
需要存儲指針&b1
,並且b2.wrapped_bar2
需要存儲指針&b2
。 這個( this
)指針是調用實例(非靜態)方法所需的實例。
它顯然不能是靜態類型的一部分(如自由函數指針或成員函數指針本身),因為b1
和b2
具有相同的類型但地址不同。 這意味着您至少需要編寫一個類似於
bar::bar() : wrapped_bar2{this} {}
現在,如果我們不得不這樣做,這兩個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;}
};
如果你想要一個可以同時處理自由函數和成員函數的頂級類型,你需要一些方法來隱藏這些實現差異(類型擦除)。 老實說, std::function
已經為您完成了所有這些工作,而且重新發明它有很多好處並不明顯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.