6

What unqualifies capturing lambda from being passed to apply method of std::valarray? consider following code:

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

Live on coliru http://coliru.stacked-crooked.com/a/f0407046699574fc

Tested on https://gcc.godbolt.org/
Neither GCC nor MSVC or CLang would compile the above code

kreuzerkrieg
  • 3,009
  • 3
  • 28
  • 59

1 Answers1

7

The reason is in the definition of std::valarray::apply:

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

The type of func in both members is a function type. Which when used as the parameter type of another function decays to a function pointer. Those member functions do not accept general functors. Only pointers to regular functions.

Now, a capture-less lambda has an implicit conversion operator to a function pointer. So the first lambda is converted to a int(*)(int) which is an address of regular function that can execute the lambdas body.

But lambdas that capture state cannot be converted in such a manner, and as you can see, cannot be passed as an argument to std::valarray::apply.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • any idea why it was done in the first place? maybe because it would render vectorization or parallelization optimizations not applicable on such `apply` implementation? – kreuzerkrieg Sep 03 '17 at 12:24
  • @kreuzerkrieg - `std::valarray` was conceived long before lambdas we introduced to the language for one. Also, I would imagine this is to encourage passing "pure" functions. In modern C++, this stands out, I know. – StoryTeller - Unslander Monica Sep 03 '17 at 12:26
  • ummm... they added std::begin/end specializations for C++11 for valarrays, why not add the rest of the modern stuff... Well, I guess simply the valarray is not as widely used as the rest of STL containers. – kreuzerkrieg Sep 03 '17 at 12:37
  • @kreuzerkrieg - Probably. Someone has to write a proposal for this to be inducted into the standard. If there isn't much usage, it's unlikely someone will write it. – StoryTeller - Unslander Monica Sep 03 '17 at 12:39
  • `std::ranges::for_each` can be used as an alternative, since they allow for capturing lambdas. – TOOL Feb 08 '23 at 20:52