三元运算符无法与lambda函数一起使用

15

我正在将一个lambda表达式赋值给一个std::function<double()>变量。这段代码是可行的。

if(fn_type==exponential)
    k.*variable = [=,&k](){ return initial*exp(-k.kstep*par); };
else
    k.*variable = [=,&k](){ return initial*pow(k.kstep, par); };

而且如果我想要使用三元运算符

k.*variable = (fn_type==exponential ? [=,&k](){ return initial*exp(-k.kstep*par); } : [=,&k](){ return initial*pow(k.kstep, par); });

我遇到了以下错误:

error: no match for ternary ‘operator?:’ in <awfully long template error, because this whole thing is in a class defined in a function...>

这是gcc的一个bug吗(我使用的是4.7.2版本)? 不然为什么标准会有这个限制呢?

2个回答

20
条件运算符的第二个和第三个操作数必须具有相同的类型,或者必须存在一些通用类型,可以将它们都转换为该类型,编译器会自动推断。编译器只会考虑少数几种转换方法。
你的两个lambda表达式具有不同的类型,且没有一个共同的类型可以将它们都转换为该类型(像`std::function`这样的用户定义类型的转换不能被考虑,因为可能存在无限数量的有效目标类型)。
你可以直接将每个操作数转换为`std::function`:
k.*variable = fn_type==exponential
    ? std::function<double()>([=,&k](){ return initial*exp(-k.kstep*par); })
    : std::function<double()>([=,&k](){ return initial*pow(k.kstep, par); });

但实际上,使用 if/else 更为简洁。


2
+1 为答案,另外 +1 是因为“使用 if/else 更加简洁。” - John Dibling
1
这里有一个相关的案例,它在clang和gcc上编译通过,但在MSVC上却没有:https://godbolt.org/z/4YQdVA 在我看来,这根本不应该编译通过,因为:两侧具有不同的类型。你有任何想法为什么它会编译通过吗?而谁是正确的,是MSVC还是clang和gcc? - Ben
1
@Ben,你的例子是答案中提到的少数几种情况之一,在这种情况下会发生转换,即两个lambda都会衰减为具有相同类型的函数指针。https://godbolt.org/z/WcbzhY377 - cigien
当然可以!(过去3.5年中我学到了很多!) - Ben

-2

我也遇到了这个问题 - 无法编译!

'if/else' 对我来说不好,我想要打开自动类型推断功能。

    auto memcpy_traits = 
        [&](uint8_t* line_dst, const uint8_t* curr_src, const size_t bytes_to_copy) {
            std::memcpy(line_dst, curr_src, bytes_to_copy);
            line_dst += bytes_to_copy;
            curr_src += bytes_to_copy;
    }
    :
     [&](uint8_t* line_dst, const uint8_t* curr_src, const size_t bytes_to_copy) {
     std::memcpy(line_dst, curr_src, bytes_to_copy);
     line_dst += bytes_to_copy;
     curr_src += bytes_to_copy;
     };

2
这不是一个答案。请删除它并提出一个新的问题。 - acraig5075

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接