
On 7/27/2011 11:49 PM, Jeffrey Lee Hellrung, Jr. wrote:
On Wed, Jul 27, 2011 at 4:23 PM, Edward Diener<eldiener@tropicsoft.com>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