Boost logo

Boost :

From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-11-12 04:26:52


Douglas Gregor wrote:
> On Monday 11 November 2002 04:56 am, Aleksey Gurtovoy wrote:
> [snip my limited example]
> > Hmm, interesting, so if this actually worked, we would be happy:
> >
> [snip nifty-looking is_callable implementation]
> >
> > ?
>
> Well, you need to do some trickery to make it work when R=void,
> but otherwise I think we would be _very_ happy if this worked. Is
> there a tweak to the core language that would guarantee such a thing?
>

Well, since that particular reason of type deduction failure (attempting to
call a member function on the object which type does not contain the
specified member) is not explicitly listed under 14.8.2 para 2, yes, in one
or another form. I haven't figured out yet what would be the best way
(politically and technically) to get that part of the language into the
state we would like it to have ;).

Hmm, actually, this one is _already_ required to work:

    #include "boost/mpl/bool_c.hpp"
    #include "boost/mpl/logical/and.hpp"
    #include "boost/type_traits/is_class.hpp"
    #include "boost/static_assert.hpp"

    namespace mpl = boost::mpl;

    typedef char (&no_tag)[1];
    typedef char (&yes_tag)[2];

    template< long > struct sink {};
    template<typename T> T get();

    template< typename Functor, typename R, typename T1 >
    no_tag has_call_operator_tester(...);

    template< typename Functor, typename R, typename T1 >
    yes_tag is_callable_helper(
          sink< sizeof(static_cast<R>(
              get<Functor>().Functor::operator()( get<T1>() ) // here
            ))>
        );

    template<
          typename Functor, typename R, typename T1
>
    struct has_function_call_operator
        : mpl::bool_c<
              sizeof(has_call_operator_tester<Functor,R,T1>(
                  sink<sizeof(R)>()
                ))
              == sizeof(yes_tag)
>
    {
    };

    template<
          typename Functor, typename R, typename T1
>
    struct is_callable
        : mpl::logical_and<
              boost::is_class<Functor>
            , has_function_call_operator<Functor,R,T1>
>
    {
    };

    struct her {};
    struct my { int operator()(int); };

    BOOST_STATIC_ASSERT((!is_callable<int,int,int>::value));
    BOOST_STATIC_ASSERT((!is_callable<her,int,int>::value));
    BOOST_STATIC_ASSERT((is_callable<my,int,int>::value));

The marked line falls directly under one of the 14.8.2 para 2's items:

"-- Attempting to use a type in the qualifier portion of a qualified name
that names a type when that
type does not contain the specified member [...]"

So getting 'is_callable' might be as easy as filing a bug report to your
favorite vendor(s) (and following it up until it's fixed, of course :).

Aleksey


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