Почему захватывающая лямбда не может быть применена к std::valarray?

Что не дает права захватывать лямбду от передачи apply метод std::valarray? рассмотрим следующий код:

int main()
{
    std::valarray<int> arr = {1, 2, 3, 4, 5, 6};
    auto arr1 = arr.apply([](int val) { return val * 2; }); // compiles
    int n = 3;
    auto arr2 = arr.apply([n](int val) { return val * n; }); //does not compile
    return 0;
}

Жить на колиру http://coliru.stacked-crooked.com/a/f0407046699574fc

Протестировано на https://gcc.godbolt.org/
Ни GCC, ни MSVC, ни CLang не скомпилируют приведенный выше код.

1 ответ

Решение

Причина в определении std::valarray::apply:

valarray<T> apply( T func(T) ) const;
valarray<T> apply( T func(const T&) ) const;

Тип func в обоих членах есть тип функции. Который при использовании в качестве типа параметра другой функции распадается на указатель функции. Эти функции-члены не принимают общие функторы. Только указатели на обычные функции.

Теперь лямбда без захвата имеет неявный оператор преобразования в указатель на функцию. Таким образом, первая лямбда преобразуется в int(*)(int) который является адресом обычной функции, которая может выполнять тело лямбда-выражения.

Но лямбды, которые фиксируют состояние, не могут быть преобразованы таким образом, и, как вы можете видеть, не могут быть переданы в качестве аргумента std::valarray::apply,

Другие вопросы по тегам