|
Boost : |
Subject: Re: [boost] [Review] TTI
From: Edward Diener (eldiener_at_[hidden])
Date: 2011-07-28 13:37:23
On 7/27/2011 11:49 PM, Jeffrey Lee Hellrung, Jr. wrote:
> 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();
I think this means that T must have a default constructor ?
If so, it is limiting for the enclosing type and the parameter types of
the function signature.
>
> 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( ) { } };
Can this be
struct base_t
{ void xxx(...) { } };
to avoid conflict with a user's nullary function, as a variable
parameter list is far less likely than a nullary function ?
>
> 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;
> }
Very neat. Of course T0 would have to be expanded to more possible types
for function parameter matching. Maybe a generic method for any number
of types would be possible through using Boost function types.
I will definitely add this to TTI in some form or other. Thanks for the
code !
Eddie
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk