如何将不同的函数签名映射到同一个std::map中?

问题描述 投票:-2回答:1

我遇到了一些问题,这些问题在评论中被指出,所以这是我新的最小可复制的代码示例。

#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;
}

有了这个,我就可以在静态投递 foo 变成 baz 比如用第二种方式。但为什么不能用第一种方式呢?

我问的是,。

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

我以为这两种方式是平等的,但显然在静态铸造方面,它们并不平等。为什么会这样呢?

还有,这些到底是一样还是不一样?

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

又是为什么呢?

c++ function c++11 stdmap static-cast
1个回答
1
投票

如果我对评论的理解正确,那么 std::map<Key, Value> 只是问题的一部分。你首先需要的是 Value 部分--什么样的C++类型可以容纳重载集的 f?

Jarod的评论是对的。* Jarod的评论是对的: [](auto... args){ return foo(args...)};. 这是一个单一的lambda对象,有一个重载的 operator(). 每次超载 operator() 选择您的 foo() 过载。

这就说明了最终的问题。[](auto... args){ return bar(args...)}; 是另一个lambda,有不同的类型,所以它不能进入同一个 std::map<Key, Value>.

这其实并不奇怪。当编译器看到 baz["foo"](qux),它需要 Value::operator(std::string). 这可以是一个模板实例化,但实例化不能在运行时发生。所以 Value 靠不住 "foo". C++根本没有运行时重载,这不是语言的工作方式。

@JesperJuhl也许有道理,这是一个XY问题。如果你有 foo(std::variant<int, std::string, std::vector<int>>) ? 这不是一个重载集,这是一个单一函数。在幕后,它可以派发给 foo_impl(...) 以任何你喜欢的方式。

© www.soinside.com 2019 - 2024. All rights reserved.