Boost logo

Boost :

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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk