Boost logo

Boost Users :

Subject: Re: [Boost-users] [Function] requiring an exact match in function signature?
From: Mathias Gaunard (mathias.gaunard_at_[hidden])
Date: 2010-04-03 15:51:48


Nathan Ridge a écrit :
>> Anyway, if you want to test the signature of a function object, just
>> take the address of &T::operator() and check it is what you want. Of
>> course that won't work if it's a template or if it is overloaded.
>
> Could you be kind enough to give an example of how I can do such a check?

This works on GCC, haven't tested with other compilers.

#include <boost/mpl/bool.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/member_function_pointer.hpp>
#include <boost/function_types/property_tags.hpp>

template<class X, class Prototype> struct function_to_member
{
     typedef typename
boost::function_types::result_type<Prototype>::type result;
     typedef typename
boost::function_types::parameter_types<Prototype>::type args;
     typedef typename boost::mpl::push_front<args, X*>::type
       base;
     typedef typename boost::mpl::push_front<base, result>::type
       type;
};

template<class X, class Prototype> struct build_member_type
{
     typedef typename function_to_member<X,Prototype>::type
           root;
     typedef typename
boost::function_types::member_function_pointer<root>::type type;
};

template<class X, class Prototype> struct build_const_member_type
{
    typedef typename function_to_member<X,Prototype>::type root;
    typedef typename boost::function_types::member_function_pointer<
       root,
       boost::function_types::const_qualified
>::type type;
};

template<class T, typename Sig>
struct has_signature
{
     typedef char not_found;
     struct found { char x[2]; };

     template<typename X, typename build_member_type<X, Sig>::type>
     struct member {};

     template<typename X, typename build_const_member_type<X, Sig>::type>
     struct const_member {};

     template<typename X> static found test(member<X, &X::operator()>*);
     template<typename X> static found test(const_member<X,
&X::operator()>*);
     template<typename X> static not_found test(...);

     static const bool value = (sizeof(found) == sizeof(test<T>(0)));
     typedef boost::mpl::bool_<value> type;

};

example of use:

struct foo { int operator()(short) const; };
struct bar { int operator()(short); };
struct baz { int operator()(int); };

int main()
{
   std::cout << has_signature<foo, int(short)>::value << std::endl; // 1
   std::cout << has_signature<bar, int(short)>::value << std::endl; // 1
   std::cout << has_signature<baz, int(short)>::value << std::endl; // 0
}


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