我遇到了一些问题,这些问题在评论中被指出,所以这是我新的最小可复制的代码示例。
#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;
又是为什么呢?
如果我对评论的理解正确,那么 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(...)
以任何你喜欢的方式。