C++ &引用;“调用”没有匹配的函数;创建函数变量向量时出错
我正在尝试创建一个C++ &引用;“调用”没有匹配的函数;创建函数变量向量时出错,c++,c++17,variant,C++,C++17,Variant,我正在尝试创建一个std::vector,它可以使用std::variant保存不同签名的std::function对象 为什么不编译以下代码: #include <functional> #include <variant> #include <vector> int main() { std::vector<std::variant< std::function< int (const std::vector<fl
std::vector
,它可以使用std::variant
保存不同签名的std::function
对象
为什么不编译以下代码:
#include <functional>
#include <variant>
#include <vector>
int main()
{
std::vector<std::variant<
std::function< int (const std::vector<float>&, int) >,
std::function< float (const std::vector<float>&, int) >
>> func_vector;
func_vector.emplace_back( [] (const std::vector<float>& ret, int index) { return ret.size(); });
return 0;
}
它说它找不到匹配的函数,但具体是为了什么调用
我试图放置的lambda正好具有我在变体中指定的一种类型的签名,所以一切都应该正常,不是吗?
放置_back
应将lambda直接转发到变体初始化。还有一个转换构造函数,它可以从任何可转换为成员类型的参数初始化变量的成员。然而,问题是变量的两个成员都可以从这个lambda初始化,从而产生歧义
是的,您的lambda是std::function
的有效初始值设定项。这是由于std::function
执行类型擦除的方式造成的。它将其持有的可调用的结果强制转换为指定的返回类型。可调用函数必须能够接受std::function
的参数列表
为了说明这一点,如果我们向std::function
类型之一添加第三个参数
std::vector<std::variant<
std::function< int (const std::vector<float>&, int) >,
std::function< float (const std::vector<float>&, int, int) >
>> func_vector;
std::vector,
std::function
>>func_向量;
然后是那里。lambda现在只是一个变量成员的有效初始值设定项
解决方法是将其转换为您希望保留的确切函数类型,或者告诉安置的变体它应该初始化哪个选项,例如:
func_vector.emplace_back( std::in_place_index<0>, [] (const std::vector<float>& ret, int ) { return ret.size(); });
func_vector.emplace_back(std::in_place_index,[](const std::vector&ret,int){return ret.size();});
std::variant
的转换构造函数的行为类似于重载解析,以确定要构造的类型
如果你有两个函数
void f(std::function< int (const std::vector<float>&, int) >);
void f(sstd::function< float (const std::vector<float>&, int) >);
void f(std::function);
void f(sstd::function);
然后电话
f([] (const std::vector<float>& ret, int index) { return ret.size(); })
f([](const std::vector&ret,int index){return ret.size();})
如果参数可以使用类型const std::vector&
和int
调用,并且返回类型可以隐式转换为int
或float
,则std::function
的构造函数也会参与重载解析。这些类型不需要完全相同
因此,这两种重载对于您的lambda都是可能的,因为它们都需要一个用户定义的转换(从lambda类型转换为
std::function
),因此重载的解决方案是不明确的。非常感谢您的回答!如果您已经演示了如何解决这个问题,那就更好了。@Alex一个不需要修改emplace\u back
的干净解决方案可能是围绕std::function
编写一个包装类,只有在类型完全匹配的情况下才能启用其构造函数。我现在没时间写出来。
f([] (const std::vector<float>& ret, int index) { return ret.size(); })