Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
276 views
in Technique[技术] by (71.8m points)

c++ - How to store functional objects with different signatures in a container?

So imagine we had 2 functions (void : ( void ) ) and (std::string : (int, std::string)) and we could have 10 more. All (or some of them) take in different argument types and can return different types. We want to store them in a std::map, so we get an API like this:

//Having a functions like:
int hello_world(std::string name, const int & number )
{
    name += "!";
    std::cout << "Hello, " << name << std::endl;
    return number;
}
//and
void i_do_shadowed_stuff()
{
    return;
}

//We want to be capable to create a map (or some type with similar API) that would hold our functional objects. like so:
myMap.insert(std::pair<std::string, fun_object>("my_method_hello", hello_world) )
myMap.insert(std::pair<std::string, fun_object>("my_void_method", i_do_shadowed_stuff) )
//And we could call tham with params if needed:
int a = myMap["my_method_hello"]("Tim", 25);
myMap["my_void_method"];

I wonder how to put many different functions into the same container. Specifically, how to do this in C++03 using Boost.

The API should be independent from the actual function types (having int a = myMap["my_method_hello"]("Tim", 25); not int a = myMap<int, (std::string, int)>["my_method_hello"]("Tim", 25);).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
#include <functional>
#include <iostream>
#include <string>
#include <map>

class api {
    // maps containing the different function pointers
    typedef void(*voidfuncptr)();
    typedef int(*stringcrintptr)(std::string, const int&);

    std::map<std::string, voidfuncptr> voida;
    std::map<std::string, stringcrintptr> stringcrint;
public:
    // api temp class
    // given an api and a name, it converts to a function pointer
    // depending on parameters used
    class apitemp {
        const std::string n;
        const api* p;
    public:
        apitemp(const std::string& name, const api* parent)
            : n(name), p(parent) {}
        operator voidfuncptr()
        { return p->voida.find(n)->second; }
        operator stringcrintptr()
        { return p->stringcrint.find(n)->second; }
    };

    // insertion of new functions into appropriate maps
    void insert(const std::string& name, voidfuncptr ptr)
    { voida[name]=ptr; }
    void insert(const std::string& name, stringcrintptr ptr)
    { stringcrint[name]=ptr; }
    // operator[] for the name gets halfway to the right function
    apitemp operator[](std::string n) const
    { return apitemp(n, this); }
};

Usage:

api myMap; 

int hello_world(std::string name, const int & number )
{
    name += "!";
    std::cout << "Hello, " << name << std::endl;
    return number;
}

int main()
{
    myMap.insert("my_method_hello", &hello_world );
    int a = myMap["my_method_hello"]("Tim", 25);
}

Not very pretty. Better advice is to not do anything even remotely like whatever it is you're trying to do.

Note that this requires all functions with the same parameters to return the same type.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...