As mentioned in https://discourse.llvm.org/t/rfc-extend-ranges-infrastructure-to-better-match-c-20/65377
Lambda objects are not copy assignable, and therefore neither are iterator types which hold a lambda. STL code require iterators be copy assignable. Users may not use mapped_iterator with a std::deque for example: https://godbolt.org/z/4Px7odEEd
This blog post explains the problem and solution. We define a wrapper class to store callable objects with two specialization.
- Specialization for non-function types
- Use a std::optional as storage for non-function callable.
- Define operator=() implementation(s) which use std::optional::emplace() instead of the assignment operator.
- Specialization for function types
- Store as a pointer (even if template argument is a function reference).
- Default construct pointer to nullptr.
This Callable wrapper class is now default constructible (with invalid state) and copy/move assignable.
With these new properties available on the callable object, mapped_iterator can define a default constructor as well.
When I configure with -DLLVM_ENABLE_EXPENSIVE_CHECKS=ON, build this test with ninja ADTTests then run this, I get the following crash from this statement:
/usr/lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/debug/safe_iterator.h:472: In function: bool gnu_debug::operator==(const _Self &, const _Self &) Error: attempt to compare a singular iterator to a dereferenceable (start-of-sequence) iterator. Objects involved in the operation: iterator "lhs" @ 0x7ffcc2f77420 { state = singular; } iterator "rhs" @ 0x7ffcc2f77450 { state = dereferenceable (start-of-sequence); references sequence @ 0x7ffcc2f772f0 }Any ideas how best to fix this?