我在编写lambda表达式时偶然发现了一个奇怪的问题。这是代码:
domainlogic
我认为可以使用的原始代码是 C 。他们基本上都做同样的事情。 GCC和Clang(Atom& finter使用)产生:
说操作数不是同一类型。这对我来说很奇怪。我的假设是每个lambda表达式都有一个独特的类型,但这并不能解释展览B的作用。为什么不在B工作时不工作?只是编译器在确定lambda类型时做出了疯狂的猜测吗?
所以,我的问题是:
为了澄清,#if 1 /* exhibit A */
const auto giveup = this->__randomGiveUp();
auto evtFunc = [this, giveup]() {
this->__acquireLock();
if (giveup) {
this->__releaseLock();
}
};
#endif
#if 0 /* exhibit B */
auto evtFunc = this->__randomGiveUp() ? (std::function<void()>)[this]() {
this->__acquireLock();
this->__releaseLock();
} : [this]() {
this->__acquireLock();
};
#endif
#if 0 /* exhibit C */
auto evtFunc = this->__randomGiveUp() ? [this]() {
this->__acquireLock();
this->__releaseLock();
} : [this]() {
this->__acquireLock();
};
#endif
#if 0 /* exhibit D */
std::function<void()> evtFunc = this->__randomGiveUp() ? [this]() {
this->__acquireLock();
this->__releaseLock();
} : [this]() {
this->__acquireLock();
};
#endif
this->__eventCtx.addEvent(this->__tickStart + this->__randomAcquireDelay(), evtFunc);
的返回类型是bool。
答案 0 :(得分:2)
每个lambda函数都有自己独特的类型。这就是C和D不起作用的原因:第二个和第三个操作数之间没有转换。如果两个操作数都不属于该类型,则C ++不会尝试转换为某些不相关的类型,例如std::function
。
这解释了为什么B工作:第二个运算符的类型为std::function<>
,第三个操作数的lambda函数类型可以通过std::function
构造函数转换为第二个操作数的类型。
答案 1 :(得分:0)
每个lambda表达式都有自己独特的类型,需要进行转换(然后再说一次B怎么运行?)
是的,他们是。 lambda表达式的结果是未命名类型的函数对象。你必须把它包装成std::function
或一些可以从lambda初始化的类似模板,以免lambda表达式是无捕获的(空捕获列表)。后者可以转换为函数指针,因此可以与三元一起使用(这里的Microsoft编译器可能会认为不同,因为它有几个函数类型的中间指针,在调用约定方面不同):
double (*square)(double) = [](double a)->double { return a*a; };
auto foo = (square) ? [](double a)->double { return a*a; } :
[](double a)->double { return a*a*a; };
B变体似乎通过三元运算符的机制隐式地(或者更确切地说,使用适当的构造函数创建std::function
对象)执行第二个操作数的转换。您可以在此处查看:Ternary operator of different types