ternary operator doesn't work with lambda func

2020-08-09 11:13发布

问题:

I am assigning to a std::function<double()> a lambda expression. This snippet works

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

whereas if I want to use the ternary operator

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

I get the following error:

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

Is this a gcc bug (I'm using 4.7.2)? Otherwise why is there this limit in the standard?

回答1:

The second and third operands of the conditional operator must have the same type or there must be some common type to which they can both be converted that the compiler can figure out. There are only a handful of conversions that the compiler will consider.

Your two lambda expressions have different types, and there is no common type to which they can both be converted (conversions to user-defined types, like std::function<double()>, cannot be considered because there are potentially an infinite number of valid target types).

You can directly convert each of the operands to std::function<double()>:

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); });

But really, it's cleaner with the if/else.



回答2:

Also faced this issue - won't compile!

'if/else' not good for me, I would like auto type deducing feature turn on.

    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;
     };