Subject: Re: [boost] [TypeTraits] propose new callable-type call traits
From: TONGARI J (tongari95_at_[hidden])
Date: 2014-01-13 08:43:54


2014/1/13 Hui Li <hui.li_at_[hidden]>

>
> On Jan 12, 2014, at 12:11 PM, TONGARI J <tongari95_at_[hidden]> wrote:
>
> > No. I just advertised this to the community and tried to gather interest
> > sometime ago, but didn't go for further review process.
> >
> > Well, doc/test are there, but no certain plan yet, I haven't got the time
> > to try out modular Boost myself.
> > So, please go ahead, it'd be great if you could bring this into Boost
> > eventually.
>
> I see. I'll look into modular boost.
> Here is my proposal to extend your boost::has_call.
> Please let me know what you think, and I'd love to hear feedback from
> anyone.
>
> 1. Guard the current limited has_call implementation with #ifdef
> BOOST_NO_SFINAE_EXPR.
>
> 2. when sfinae-expr is supported, implement has_call based on sfinae
> expression (my approach or something similar).
> This would make has_call evaluate to false when the call is ambiguous
> on c++03 compilers that support sfinae-expr, which makes it closer to your
> original intent.
>
> 3. add has_ambiguous_call<T,R(Args...)> to both the unlimited
> implementation, and to the limited implementation when sfinae-expr is
> available.
> The return-type R is ignored.
>
> 4. add has_no_viable_call<T,R(Args)> to both the unlimited implementation,
> and to the limited when sfinae-expr is available, which always evaluate to
> has_no_viable_call<T,R(Args)>::value == ! has_call<T,R(Args)>::value
> && ! has_ambiguous_call<T,R(Args)>::value
> note that this means it evaluates to false when the
> decltype(T(Args...)) is not convertible to R, which i think is the correct
> behavior. also note that, for any given <T,R(Args...)>, one and only one of
> the three traits would evaluate to true.
>
> 5. to achieve some degree of consistency when there is no sfinae-expr
> support, we should have (by definition if you like),
> has_ambiguous_call<T,R(Args)>::value == false; // because
> has_call<T,R(Args)> does not compile when ambiguous
> has_no_viable_call<T,R(Args)>::value == ! has_call<T,R(Args)>::value
>

I'll explain some of my original design rationale here:

1) Name choosing:
"has_call" was originally called "can_be_called", and was intended to be a
separate lib than TypeTraits, but as someone pointed out, TypeTraits seems
a good place, and since there are already Operator Type Traits which is
called has_xxx, I just followed the convention.

2) Return Type Specifying:
other Operator Type Traits let you specify the expected return type, so I
followed, though with a bit different syntax.

But since you also tried to provide more than has_call, I'm not sure if
these apply to the others.
For example, has_ambiguous_call doesn't have to follow the convention as
has_call as you want to ignore the return type, maybe you can make it
is_ambiguous<T(A...)>.

Another thought is: maybe you don't have to make has_ambiguous_call
a first-class citizen, you can provide something like has_call_fuzzy which
is the exact opposite of has_no_viable_call, then the user with c++11
available can opt to use has_call_fuzzy instead of has_call so the error
will generate if the call is ambiguous.

About the compatibility of has_ambiguous_call -- I'm not sure if telling
the false negative or generating a compile error is better in case that the
compiler is incapable to tell the truth.