我正在尝试创建一个std::vector可以std::function使用std::variant.
为什么以下代码无法编译:
#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;
}
Run Code Online (Sandbox Code Playgroud)
问题发生在emplace_back(). 编译这个会给出一长串错误,列出的第一个是:
error: no matching function for call to ‘std::variant<std::function<int(const std::vector<float, std::allocator<float> >&, int)>, std::function<float(const std::vector<float, std::allocator<float> >&, int)> >::variant(main()::<lambda(const std::vector<float>&, int)>)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
它说它找不到匹配的函数,但是究竟是什么调用呢?
我试图放置的 lambda 恰好具有我在变体中指定的类型之一的签名,所以一切都应该没问题,不是吗?
emplace_back应该将 lambda 直接转发到变量初始化。并且有一个转换构造函数可以从任何可转换为成员类型的参数初始化变体的成员。然而,问题是变体的两个成员都可以从此 lambda 初始化,从而产生歧义。
是的,您的 lambda 是std::function< float (const std::vector<float>&, int) >. 这是由于std::function执行类型擦除的方式。它将它持有的可调用结果转换为它指定的返回类型。callable 只需要能够接受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;
Run Code Online (Sandbox Code Playgroud)
那么就不会有歧义了。lambda 现在仅是一个变体成员的有效初始值设定项。
解决方法是要么强制转换为您希望保留的确切函数类型,要么告诉放置的变体它应该初始化哪个选项,例如:
func_vector.emplace_back( std::in_place_index<0>, [] (const std::vector<float>& ret, int ) { return ret.size(); });
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1308 次 |
| 最近记录: |