简体   繁体   English

将通用 function 分配给 function 指针结构成员

[英]Assign generic function to function pointer struct memeber

I have to assign the following member of a struct:我必须分配结构的以下成员:

esp_err_t (*handler)(httpd_req_t *r);

As you can see, it is a function pointer.如您所见,它是一个 function 指针。 I have a generic template function that I would like to assign as handler :我有一个通用模板 function 我想指定为handler

template <class Tmsg>
esp_err_t HandleRpc(httpd_req_t *req){...}

I am assigning the handler member inside a generic template class, so I have a generic type argument Tpayload :我在通用模板 class 中分配handler成员,所以我有一个通用类型参数Tpayload

httpd_uri_t cfg = {
    ...
    .handler = HandleRpc<Tpayload>,
    ...
};

I get:我得到:

expected primary-expression before '>' token '>' 标记之前的预期主表达式

The issue lies in the fact that I can't pass a member method pointer (IE esp_err_t (RpcServer::*)(...) ), but RpcServer is a generic template class (IE has a template with one generic parameter).问题在于我无法传递成员方法指针(IE esp_err_t (RpcServer::*)(...) ),但RpcServer通用模板 class (IE 有一个带有一个通用参数的模板)。 So I thought that by creating a generic template function outisde the class (global scope?), and passing the RpcServer instance into that function, I would be able to retrieve my instance of RpcServer<T> and all would be well. So I thought that by creating a generic template function outisde the class (global scope?), and passing the RpcServer instance into that function, I would be able to retrieve my instance of RpcServer<T> and all would be well.

Here is the smallest amount of code I could come up with to reproduce the issue:这是我能想出的重现该问题的最少代码量:

int main()
{
    
}

template <class T>
class RpcServer{
    public:
        void RegisterHandler();
};

struct HandlerInfo{
    void (*handler)();
};

template <class T>
void Handle(RpcServer<T> test)
{

}

template <class T>
void RpcServer<T>::RegisterHandler(){
    HandlerInfo info = {
        .handler = Handle<T>;
    };
}

Am I missing the obvious, or is what I am trying to do going to require some uglier trickery?我错过了显而易见的事情,还是我想做的事情需要一些更丑陋的诡计?

struct HandlerInfo{
    void (*handler)();
};

handler is a pointer to a function that takes no parameters, and doesn't return anything. handler是一个指向 function 的指针,它不带参数,也不返回任何东西。 You can set this pointer to point to any function.您可以将此指针设置为指向任何 function。 As long as it takes no parameters, and doesn't return anything (its return type is void ).只要它不带参数,并且不返回任何东西(它的返回类型是void )。 There are no exceptions to this, this is how C++ works, it is a strongly-typed language.这一点也不例外,这就是 C++ 的工作原理,它是一种强类型语言。

template <class T>
void Handle(RpcServer<T> test)
{

This is a template for a function that takes one parameter.这是采用一个参数的 function 的模板。 The type of the parameter is not material.参数的类型不重要。 The point is that every instance of this template will be a function that takes exactly one parameter, always.关键是这个模板的每个实例都是一个 function,它总是只接受一个参数。

In C++, a pointer to a function that has no parameters can only be set to point to such a function.在C++中,指向没有参数的function的指针只能设置为指向这样的function。 You cannot set this function pointer to point to a function that takes one parameter, or two parameters, or ten parameters.您不能将此 function 指针设置为指向一个 function 接受一个参数、两个参数或十个参数。 It can only be set to a function that takes exactly zero parameters.它只能设置为采用零参数的 function。 That's because that's what the pointer points to.那是因为那是指针所指向的。

If you were to change the template function so that it takes no parameters, then this would work, of course:如果您要更改模板 function 使其不带参数,那么这当然可以:

int main()
{

}

template <class T>
class RpcServer{
    public:
        void RegisterHandler();
};

struct HandlerInfo{
    void (*handler)();
};

template <class T>
void Handle()
{

}

template <class T>
void RpcServer<T>::RegisterHandler(){
    HandlerInfo info = {
            .handler = Handle<T>
    };
}

This compiles on gcc 10. ".member" initialization syntax has been supported by gcc for a long time, but it's only been standardized as of C++20, so other compilers may not support this syntax.这在 gcc 10 上编译。“.member”初始化语法已被 gcc 支持很长时间,但它只是在 C++20 时才标准化,因此其他编译器可能不支持此语法。

You could, if you wish, declare this to be a pointer to a function that takes an RpcServer<int> as its parameter:如果您愿意,可以将其声明为指向以RpcServer<int>作为参数的 function 的指针:

struct HandlerInfo{
    void (*handler)(RpcServer<int>);
};

Now, you will be able to initialize it to point to such a function:现在,您将能够将其初始化为指向这样的 function:

HandlerInfo info = {
    .handler = Handle<int>
};

HandleInt instantiates a function that takes such a parameter, so the types match exactly. HandleInt实例化了一个采用此类参数的 function,因此类型完全匹配。

Or, alternatively, make HandlerInfo itself a matching template:或者,或者,使HandlerInfo本身成为匹配模板:

template <class T>
class RpcServer{
    public:
        void RegisterHandler();
};

template<class T>
struct HandlerInfo{
    void (*handler)(RpcServer<T>);
};

template <class T>
void Handle(RpcServer<T> )
{

}

template <class T>
void RpcServer<T>::RegisterHandler(){
    HandlerInfo<T> info = {
        .handler = Handle<T>
    };
}

int main()
{
    RpcServer<int> server;

    server.RegisterHandler();
}

(Note -- your code has other syntax errors; if they were fixed it would seem that, at first, the code would compie; but if an attempt was made to instantiate the templates, it would fail due to the type mismatch) (注意——你的代码有其他语法错误;如果它们被修复,看起来,一开始,代码会编译;但如果尝试实例化模板,它会由于类型不匹配而失败)

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

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