简体   繁体   中英

How to map different function signatures into the same std::map?

I had some issues which were pointed in the comments, so this is my new minimal reproducible code sample;

#include <functional>
#include <iostream>
#include <vector>
#include <map>
std::string foo(int bar)
{
    return std::to_string(bar); 
}
std::string foo(std::vector<int> bar)
{
    int baz;
    //process
    return foo(baz);
}
std::string foo(std::string bar)
{
    std::vector<int> baz;
    //process
    return foo(baz);
}
int main()
{
    std::map<std::string,std::function<std::string(std::string)>> baz;
    //error baz["foo"]=static_cast<std::function<std::string(std::string)>>(&foo);
    /*working*/baz["foo"]=static_cast<std::string(*)(std::string)>(&foo);
    std::string qux;
    std::cout<<baz["foo"](qux)<<std::endl;
}

Given this, I can do what I intend when I static cast foo into baz like in second way. But why can't it be done in the first way?

What I ask, is that;

(<std::function<std::string(std::string)> == std::string(*)(std::string))

I thought these two would be equal, but apparently when it comes to static cast, they're not.
Why so?

Also, are these same or not?

std::map<std::string,std::function<std::string(std::string)>> baz;
std::map<std::string,std::string(*)(std::string)> baz;

And why?

If I understand the comments correctly, the std::map<Key, Value> is only part of the problem. You first need the Value part - what C++ type can hold the overload set of f ?

Jarod's comment is right: You basically need [](auto... args){ return foo(args...)}; . This is a single lambda object, with an overloaded operator() . Each overload of operator() selects one of your foo() overloads.

This then shows the ultimate problem. [](auto... args){ return bar(args...)}; is another lambda, with a different type, so it can't go in the same std::map<Key, Value> .

That's really no surprise. When the compiler sees baz["foo"](qux) , it needs Value::operator(std::string) . That can be a template instantiation, but an instantiation cannot happen at runtime. So Value can't depend on "foo" . C++ simply does not have run-time overloading, that is not how the language works.

@JesperJuhl may have a point that this is an XY problem. What if you had foo(std::variant<int, std::string, std::vector<int>>) ? This is not an overload set; this is a single function. Behind the scenes, it can dispatch to foo_impl(...) in any way you like.

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