$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [Fit] Formal review / Kris
From: Paul Fultz II (pfultz2_at_[hidden])
Date: 2016-03-21 17:52:03
On Monday, March 21, 2016 at 4:30:16 PM UTC-5, Louis Dionne wrote:
>
> Paul Fultz II wrote 
> > On Monday, March 21, 2016 at 8:34:16 AM UTC-5, Louis Dionne wrote: 
> >> 
> >> [...] 
> >> 
> >> I'm not sure I understand what you mean. I mean, it is expected that 
> >> the function is never called when the first one could be called, since 
> >> it's overload _linearly_, right? 
> >> 
> > 
> > Yes, but another way to achieve that is to use a ranked tag-dispatching. 
> > Like this: 
> > 
> > template 
> > <int N> 
> > struct rank : rank 
> > <N-1> 
> > {}; 
> > 
> > template<> 
> > struct rank<0> 
> > {}; 
> > 
> > // Call F 
> > template 
> > <class... Ts> 
> > auto foo_impl(Ts&&... xs, rank<1>) 
> > -> decltype(std::declval 
> > <F> 
> > ()(std::forward 
> > <Ts> 
> > (xs)...)); 
> > 
> > // Call G 
> > template 
> > <class... Ts> 
> > auto foo_impl(Ts&&... xs, rank<0>) 
> > -> decltype(std::declval 
> > <G> 
> > ()(std::forward 
> > <Ts> 
> > (xs)...)); 
> > 
> > template 
> > <class... Ts> 
> > auto foo_impl(Ts&&... xs) 
> > -> decltype(foo_impl(std::forward 
> > <Ts> 
> > (xs)..., rank<1>{})); 
> > 
> > So `G` will not be called if `F` is callable, however, the compiler will 
> > instantiate both `F` and `G` with this implementation. I used to use an 
> > implementation like this, but it is more costly at compile time. 
> > Furthermore, 
> > lazy instantiation is nice feature as well, especially when using 
> > constexpr, 
> > as the body of a constexpr function is always instantiated during 
> > substitution. 
> >   
>
> I'm very surprised to learn that the compiler will instantiate both F and 
> G 
> in the code you posted above. Can't the compiler determine that the first 
> `foo_impl` should be chosen if `decltype(std::declval<F>()(...))`does not 
> SFINAE out because rank<1> is a better match than rank<0>, and this 
> without ever looking at `std::declval<G>()(...)`? 
>
I would think it would more complicated for the compiler to build a 
structure
to know that.
 
>
> Anyway, IIUC, `hana::overload_linearly` has this problem, so I'll change 
> it. 
> Thanks for the heads up. 
>
After looking at it closer, I don't think Hana has that problem, because you
never invoke the second function when the function is picked. You do 
something
like this instead:
template<int N>
struct rank : rank<N-1>
{};
template<>
struct rank<0>
{};
// pick F
template<class... Ts, 
    // Constraint on this function for when F is not callable
    class=decltype(std::declval<F>()(std::forward<Ts>(xs)...))>
F foo_which(rank<1>) { return F(); }
// pick G, there is no constraint
template<class... Ts>
G foo_which(rank<0>) { return G(); }
template<class... Ts>
decltype(auto) foo(Ts&&... xs)
{
    return foo_which<Ts&&...>(rank<1>{})(std::forward<Ts>(xs)...);
}
So the call to `G` will never get instantiated until its picked.
 
>
> Louis 
>
>
>
>
> -- 
> View this message in context: 
> http://boost.2283326.n4.nabble.com/Fit-Formal-review-Kris-tp4684694p4684785.html 
> Sent from the Boost - Dev mailing list archive at Nabble.com. 
>
> _______________________________________________ 
> Unsubscribe & other changes: 
> http://listarchives.boost.org/mailman/listinfo.cgi/boost 
>