简体   繁体   English

如何将非静态成员函数传递给模板参数?

[英]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);
}

Working demo工作演示

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.它显然不能是静态类型的一部分(如自由函数指针或成员函数指针本身),因为b1b2具有相同的类型但地址不同。 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.

相关问题 如何将非静态成员函数作为模板参数传递给另一个成员函数? - How to pass non-static member function as template argument to another member function? 如何使用非静态成员 function 作为模板参数? - Howto use non-static member function for template argument? 如何将非静态成员函数指针传递给 C++ 中的模板函数 - How to pass non-static member function pointer to a template function in C++ 将非静态成员函数作为参数传递 - Passing Non-Static Member Function as argument 传递非静态成员函数作为回调 - Pass non-static member function as a callback 如何将非静态成员函数传递给 ftw? - How can I pass a non-static member function to ftw? 传递成员 function 作为参数错误:“必须调用对非静态成员 function 的引用” - Pass a member function as argument error: “reference to non-static member function must be called” 将非静态成员函数作为参数传递给成员函数 - Passing non-static member function as argument to member function 将非静态成员 function 传递给另一个 class 的成员 function - Pass non-static member function to member function of another class Invalid use of a non-static member function - How to pass a function pointer of a member function to a non-member function? - Invalid use of a non-static member function - How to pass a function pointer of a member function to a non-member function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM