Boost logo

Boost :

Subject: Re: [boost] [Review] TTI
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2011-07-27 23:49:17


On Wed, Jul 27, 2011 at 4:23 PM, Edward Diener <eldiener_at_[hidden]>wrote:
[...]

> I am interested in what you may be trying to do here, so that is why I am
> pointing this out.
>
> Can you correct and explain what you are doing again ? I would like to
> understand the technique for checking convertibility.
>
[...]

The following program should illustrate the basic idea. Obviously, this is
pretty minimalistic, so it doesn't take into account constness, only checks
unary member functions, doesn't account for void result types, etc.

Tested on MSVC9.

--------

#include <boost/mpl/and.hpp>
#include <boost/static_assert.hpp>

template< class T > T declval();

struct yes_type { char _dummy[1]; };
struct no_type { char _dummy[2]; };

template< class T >
struct is_convertible
{
    static yes_type apply(T);
    static no_type apply(...);
};

struct dummy_result_t { };
yes_type is_dummy_result_t(dummy_result_t);
no_type is_dummy_result_t(...);

struct base_t
{ void xxx( ) { } };

template< void (base_t::*)( ) >
struct has_mem_fn_detector
{ typedef no_type type; };

template< class T >
typename has_mem_fn_detector< &T::xxx >::type
has_mem_fn_test(int);

template< class T >
yes_type
has_mem_fn_test(...);

template< class T >
struct derived_t : T
{
    using T::xxx;
    dummy_result_t xxx(...) const;
};

template< class T, class Signature >
struct has_mem_fn_helper;

template< class T, class Signature = void >
struct has_mem_fn
    : boost::mpl::and_<
          has_mem_fn< T, void >,
          has_mem_fn_helper< T, Signature >
>
{ };

template< class T >
struct has_mem_fn< T, void >
{
    struct derived_t : T, base_t { };
    static const bool value = sizeof( has_mem_fn_test< derived_t >(0) ) ==
sizeof( yes_type );
    typedef has_mem_fn type;
};

template< class T, class Result, class T0 >
struct has_mem_fn_helper< T, Result ( T0 ) >
{
    static const bool value =
        (sizeof( is_dummy_result_t(declval< derived_t<T>
>().xxx(declval<T0>())) ) == sizeof( no_type ))
     && (sizeof( is_convertible< Result >::apply(declval< derived_t<T>
>().xxx(declval<T0>())) ) == sizeof( yes_type ));
    typedef has_mem_fn_helper type;
};

struct X
{ };

struct Y
{ int xxx(int); };

int main(int argc, char* argv[])
{
    BOOST_STATIC_ASSERT(!(has_mem_fn< X >::value));
    BOOST_STATIC_ASSERT( (has_mem_fn< Y >::value));
    BOOST_STATIC_ASSERT( (has_mem_fn< Y, int ( int ) >::value));
    BOOST_STATIC_ASSERT( (has_mem_fn< Y, long ( short ) >::value));
    BOOST_STATIC_ASSERT(!(has_mem_fn< Y, int ( void* ) >::value));
    BOOST_STATIC_ASSERT(!(has_mem_fn< Y, void* ( int ) >::value));
    return 0;
}
--------

- Jeff


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