On Fri, 6 Mar 2020, Jonathan Wakely wrote:

> On 05/03/20 11:02 -0500, Patrick Palka wrote:
> > This works around PR 93978 by avoiding having to instantiate ranges::empty()
> > when checking the constraints of view_interface::operator bool().  When
> > ranges::empty() has an auto return type, then we must instantiate it in
> > order to
> > determine whether the requires expression { ranges::empty(_M_derived()); }
> > is
> > well-formed.  But this means instantiating view_interface::empty() and hence
> > view_interface::_M_derived(), all before we've yet deduced the return type
> > of
> > join_view::end().  (The reason view_interface::operator bool() is needed in
> > join_view::end() in the first place is because in this function we perform
> > direct initialization of join_view::_Sentinel from a join_view, and so we
> > try to
> > find a conversion sequence from the latter to the former that goes through
> > this
> > conversion operator.)
> > 
> > Giving ranges::empty() a concrete return type of bool should be safe
> > according
> > to [ranges.prim.empty]/4 which says "whenever ranges::empty(E) is a valid
> 
> N.B. [range.prim.empty] in the commit log here please, not "ranges."

Fixed.

> 
> > expression, it has type bool."
> 
> Right, I don't know why I didn't make it just return bool anyway.
> Probably because I was copy&pasting _Begin for each of those other
> range access CPOs.
> 
> This way we've become aware of the danger of using deduced return
> types, and so can audit the other cases.

It seems that all of the other range access CPOs (since they are each
defined with a deduced return type) have some form of this issue: using
them as an unevaluated operand may cause more templates to get
instantiated than when using the corresponding expression-equivalent
expression.  In this specific case, checking the constraint

    requires { ranges::empty(_M_derived()); }

requires instantiating the body of _Derived::empty(), whereas checking
the expression-equivalent constraint

    requires { _M_derived().empty(); }

doesn't.  If this discrepancy is important, then it seems we need to
avoid using a deduced return type in the definitions of each of these
CPOs.  Is this worth doing?

> 
> > This fixes the test case in PR 93978 when compiling without -Wall, but with
> > -Wall
> > the test case still fails due to the issue described in PR c++/94038, I
> > think.
> > I still don't quite understand why the test case doesn't fail without -O.
> 
> Still a small improvement.
> 
> OK for master, thanks.

Reply via email to