Подтвердить что ты не робот

Тернарный оператор не работает с лямбда-функциями

Я назначаю выражение 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-ошибкой (я использую 4.7.2)? В противном случае, почему это ограничение в стандарте?

4b9b3361

Ответ 1

Второй и третий операнды условного оператора должны иметь один и тот же тип или должен быть некоторый общий тип, к которому оба они могут быть преобразованы, которые компилятор может определить. Есть только несколько конверсий, которые рассмотрит компилятор.

Два ваших лямбда-выражения имеют разные типы, и нет общего типа, к которому они могут быть преобразованы (преобразования в пользовательские типы, такие как std::function<double()>, не могут рассматриваться, поскольку потенциально существует бесконечное количество действительных целевых типов).

Вы можете напрямую преобразовать каждый из операндов в 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); });

Но на самом деле он чист с помощью if/else.

Ответ 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;
     };