Почему захватывающая лямбда не может быть применена к 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
,