On Wed, Oct 27, 2010 at 9:16 PM, Ioannis Papadopoulos <ipapadop@cse.tamu.edu> wrote:
Do you have any hints on how to do that? (C++0x is fine)

Thanks

Here's a quick test with mixed results, though it's fairly hacky.

//////////

#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/preprocessor/cat.hpp>
#include <iostream>

template< class T > T& make_ref();

struct some_implementation_detail_type {};

struct a {};
struct b {};
struct c {};

a foo( b );

// Note, this is a very basic example. A good macro would parenthesize to the
// arguments to allow commas to be present in the types, and it could be
// variadic or take a preprocessor sequence to allow any number of parameter
// types.
#define IS_CALLABLE( type_name, fun_name, return_type, param_type )\
template< class ParamType >\
decltype( ::boost::is_same< return_type\
, decltype( fun_name( ::make_ref< ParamType >() ) ) >() )\
BOOST_PP_CAT( detail ## type_name ## impl, __LINE__ )( int );\
template< class ParamType, class T >\
::boost::mpl::false_ \
BOOST_PP_CAT( detail ## type_name ## impl, __LINE__ )( T );\
void fun_name( ::some_implementation_detail_type );\
typedef decltype( BOOST_PP_CAT( detail ## type_name ## impl, __LINE__ )\
< param_type >( 0 ) ) type_name;

// These macro invocations just produce typedefs
IS_CALLABLE( foo_a_b_exists, foo, a, b )
IS_CALLABLE( foo_a_c_exists, foo, a, c )
IS_CALLABLE( bar_a_b_exists, bar, a, b )

int main()
{
  // Outputs 1 0 0
  std::cout << foo_a_b_exists::value << std::endl
            << foo_a_c_exists::value << std::endl
            << bar_a_b_exists::value << std::endl;
}

//////////

The idea is to check if the function call expression is valid by forcing such an expression to be dependent on a template argument (which has the side-effect of bringing in ADL -- this is also why I stated in my first reply that the arity of the function couldn't be 0). Then, there is a separate overload that is a worse match which will be picked up if substitution fails on the template exploiting SFINAE. The check works by attempting to call the function and examining the result type to determine which template overload was picked. Everything is in decltype so no functions are actually called and the result just a typedef from which you can get a compile-time constant.

So, to be precise, using the check can't tell you if a function matches your EXACT function signature in a specific namespace, but you can see if such a function call would be a valid expression, which for many purposes is all that you'd want anyway. It's a hack, but it should work for at least some definition of work.

--
-Matt Calabrese