简体   繁体   中英

Generic function implementation in C++

I'm working on a new platform and my code is:

Layer1:

Call_To_Layer2 (param1, param2);

Layer2:

Call_To_Layer2(param1, param2)
{
    Dispatch_Work_To_Thread(param1, param2);
}

Dispatch_Work_To_Thread(param1, param2)
{
    // create a new thread and execute the task
}

The function call from Layer1 can have any number of parameters. So how can I design such a method in Layer2? Dispatch_Work_To_Thread method in layer2 requires the function name as one of the parameters. Since the number of parameters is not constant, how can this be designed?

I have pondered about the design for this problem, but couldn't come up with any solution till now.

One option would be to have Call_To_Layer2 and Dispatch_Work_To_Thread take an std::function<void(void)> , and create the function object out of any function name and parameters.

Layer1 functions:

void foo_layer1(param1, param2);
void bar_layer1(param1, param2);

Layer 2:

#include <functional>

Call_To_Layer2 (std::function<void(void)> f); // or reference_wrapper to std::function

f00 = std::bind(foo_layer1, param1, param2);
Call_To_Layer2(foo);  // passes it on to `Dispatch_Work_To_Thread`

If you don't have the required C++11 support, you could use boost.function and boost.bind instead.

  1. Maybe put all the parameters in a struct or a class, and pass an object to Call_To_Layer2 ? This would work if the class can encapsulate the variable factor.

  2. One other option is to use the variadic function syntax Call_To_Layer2(param1, param2, ...) .

Without more specific example it's difficult to know what the best solution is.

Variadic functions might be one option, although they are mostly considered antiquated these days.

The easiest might be to simply wrap the arguments in a std::vector or similar, and let the layer 2 code unpack them as appropriate.

This is not something that can be done portably with C++. You can however change things a little and having your functions accepting a single parameter that is a map containing all the relevant parameters:

typedef std::map<std::string, Anything> Parms;

Anything function1(const Parms& parms)
{
    double x = parms("x");
    std::string title = parms("title");
    ...
}

void init_module()
{
    register_function("function1", function1,
                      "void return, double x, string title");
}

In the above example Anything is a class that can contain any of the types you want to support as parameters or return values. I am used to code it myself but probably boost::any is ok for that. Every published function accepts only a dictionary of parameters and the function publishes also the return type and parameters. This information is stored in a map for dispatching and parameter checking so that you don't need to code checking in all functions and also allows publishing directory services.

You could also use instances of classes that implements a "call" method instead of functions for the published services (this is what I'm used to do).

Unfortunately C++ design is not very compatible with this use case and a lot of coding is required. There is no such a thing like "call the function with this name passing these parameters" where the function name and parameters are provided at runtime.

Note that this use is on the other hand not so uncommon and therefore you can find a lot of libraries that try to add this dinamicity to C++... how they fit to your exact problem, what dependencies they have and how complex they are is something that must be considered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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