C++ 无法使用各种lambda表达式初始化std::variant
我正在玩C++ 无法使用各种lambda表达式初始化std::variant,c++,lambda,future,c++17,variant,C++,Lambda,Future,C++17,Variant,我正在玩std::variant、lambdas和std::future,当我试图将它们组合在一起时,得到了非常奇怪的结果。以下是一些例子: 使用variant\u t=std::variant< std::函数, std::函数 >; auto f1=[](int){return std::async([]{return 1;});}; 自动f2=[](int){return std::async([]{});}; 变体v1(标准::移动(f1));/!!!为什么这一个不应该编译呢? auto
std::variant、lambdas
和std::future
,当我试图将它们组合在一起时,得到了非常奇怪的结果。以下是一些例子:
使用variant\u t=std::variant<
std::函数,
std::函数
>;
auto f1=[](int){return std::async([]{return 1;});};
自动f2=[](int){return std::async([]{});};
变体v1(标准::移动(f1));/!!!为什么这一个不应该编译呢?
auto idx1=v1.index()//等于1。为什么?
变型2(标准::移动(f2));/!!!为什么这个不在应该编译的时候编译呢?
以下是编译错误:
错误C2665'std::variant::variant':两个重载都没有
无法转换所有参数类型
好的,让我们将variant
的项目签名从返回void
更改为int
:
使用variant\u t=std::variant<
std::函数,
std::函数
>;
变体v1(标准::移动(f1));//编译(就像它应该做的那样)
auto idx1=v1.index();//等于0
变体v2(标准::移动(f2));//不编译(就像它应该编译的那样)
这到底是怎么回事?为什么
std::future
如此特殊 variant
的转换构造函数模板使用重载解析来确定构造对象应具有的类型。特别是,这意味着如果对这些类型的转换同样好,那么构造函数就不能工作;在您的例子中,如果可以从您的参数构造一个std::function
专门化,那么它就可以工作
那么什么时候可以从给定的参数构造函数
?从C++14开始,如果参数可以使用参数类型调用,并且生成的类型为。请注意,根据本规范,如果返回类型为void
,则任何内容都会变为(as)。如果您有一个函数
返回void
,那么您传入的functor可以返回任何特性,而不是bug!这也是为什么函数
适用于f1
。另一方面,future
不会转换为future
;因此,只有函数
是可行的,变量的索引是1
但是,在第二种情况下,lambda返回future
,可转换为future
和void
。如上所述,这使得函数
专门化都是可行的,这就是变量
无法决定构造哪一个的原因
最后,如果您将返回类型调整为
int
,则整个void
转换问题将被避免,因此一切都按预期进行 注意:std::variant
是C++17的一项功能,而不是C++11。您的编译错误来自第二个示例,但您的问题使它看起来像是来自第一个示例。谢谢您的回答。但我仍然无法想象std::future
如何隐式转换为void
(或者void
转换为std::future
——我不确定我是否理解这一点)?这是否意味着所有内容都可以转换为void
?@DmitryKatkevich这是正确的,任何表达式都可以通过static\u cast
转换为void
。否则,我们无法向函数提供当函数
产生void
时返回某些内容的函子,这是所需的特性!