繁体   English   中英

如何将重载的成员函数作为参数传递?

[英]How to pass an overloaded member-function as parameter?

这是我面临的问题:我在类中有一个重载函数,我想将其中一个重载作为参数传递。 但是这样做时,我收到以下错误:

"no suitable constructor exists to convert from <unknown-type> to std::function<...>"

这是一个代码示例来说明:

#include <functional>
#include <string>

class  Foo
{
private:
    int val1 , val2;
};    

class Bar
{
public:
    void function ( ) {
        //do stuff;
        Foo f;
        function ( f );
    }    
    void function ( const Foo& f ) {
        //do stuff
    }

private:
    //random attribute
    std::string str;    
};


void otherFunction ( std::function<void ( Bar& , const  Foo& ) > function ) {
    Bar b;
    Foo f;
    function(b,f);
}

int main ( ) {    
    otherFunction ( &Bar::function );
                    ^^^
                   error
}

我理解编译器无法推断出要使用哪个重载,所以接下来最好的事情是static_cast ,但是下面的代码仍然有相同的错误

std::function<void ( Bar& , const Foo& )> f = static_cast< std::function<void ( Bar& , const Foo& )> > ( &Bar::function );

你需要强制转换成成员函数指针,而不是std::functionstd::function

otherFunction ( static_cast<void(Bar::*)(const Foo&)>(&Bar::function) );

生活

[编辑]

说明:

otherFunction ( &Bar::function );

otherFunctionstd::function作为参数。 std::function有一个隐式构造函数(一个隐式转换)来自一个函数指针(一个成员函数或一个自由函数,以及其他“可调用”类型,这里没关系)。 它看起来像这样:

template< class F > 
function( F f );
  • 这是一个模板参数
  • 虽然F是“可调用的”,但它没有指定F的签名

这意味着编译器不知道你的意思是哪个Bar::function ,因为这个构造函数不对输入参数施加任何限制。 这就是编译器所抱怨的。

你试过了

static_cast< std::function<void ( Bar& , const Foo& )> > ( &Bar::function );

虽然看起来编译器具有它需要的所有细节(签名),但实际上调用了相同的构造函数,因此没有任何有效的改变。 (实际上,签名不正确,但即使是正确的签名也行不通)

通过强制转换为函数指针,我们提供了它的签名

static_cast<void(Bar::*)(const Foo&)>(&Bar::function)

所以模糊性得到解决,因为只有一个这样的函数,所以编译器很高兴。

如果使用类型化成员函数指针和模板化的otherFunction ,则代码将起作用。 这意味着,将您的otherFunction()更改为:

template<typename Class, typename T>
void otherFunction(void(Class::*)(T) ) {
    Bar b;
    Foo f;
    b.function(f);
}

如果语法混乱,请使用成员函数指针的辅助(模板)别名:

template<typename Class, typename T>
using MemFunPtr = void(Class::*)(T);

template<typename Class, typename T>
void otherFunction(MemFunPtr<Class, T> function) {
    Bar b;
    Foo f;
    b.function(f);
}

现在你可以在没有类型转换的情况下调用该函数。

int main()
{
    otherFunction(&Bar::function);
    return 0;
}

见在线

您可能需要使用宏以避免一些麻烦。

#define OVERLOADED(f) \
  [&](auto&&...xs)noexcept->decltype(auto)\
    {return std::invoke(f, decltype(xs)(xs)...);}

int main(){
  g(OVERLOADED(&Bar::function));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM