Boost logo

Boost Users :

Subject: Re: [Boost-users] Checking if a stand-alone function exists
From: Matt Calabrese (rivorus_at_[hidden])
Date: 2010-10-28 01:37:59


On Wed, Oct 27, 2010 at 9:16 PM, Ioannis Papadopoulos <ipapadop_at_[hidden]
> 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


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net