In a comment by @MarcvanLeeuwen to another Q&A, it was suggested that the following is undefined behavior (UB):
template<class FwdIt, class T>
FwdIt find_before(FwdIt before_first, FwdIt last, T const& value)
{
    return std::adjacent_find(before_first, last, 
        [&](auto const& /* L */, auto const& R) { 
        // note that the left argument of the lambda is not evaluated
        return R == value; 
    });
}
auto list = std::forward_list<int> { 1, 2 };
auto it = find_before(list.before_begin(), list.end(), 1); // undefined behavior!?
The UB comes from the fact that the BinaryPredicate that is supplied to std::adjacent_find will dereference two adjacent iterators at a time, the first pair being list.before_begin() and list.begin(). Since before_begin() is not dereferencable, this could entail UB. On the other hand, the left argument is never used inside the lambda. One might argue that under the "as-if" rule it is unobservable whether the derefence actually took place, so that an optimizing compiler might elide it altogether.
Question: what does the Standard say about dereferencing an undereferencable iterator it, when the expression *it is not actually used and could be optimized away? (or more generally, is it UB when the offending expression is not used?)
NOTE: the offending code is easy to remedy by special casing the first iterator (as is done in the updated original Q&A).
 
     
     
     
    