Question

Boost TTI has very convenient macros for checking if a type has a member function. See here.

But BOOST_TTI_HAS_MEMBER_FUNCTION returns false for inherited member functions. Is there a convenient Boost solution for this?

I am aware of an existing thread for a custom SFINAE solution. But I would prefer a Boost solution, since that way I am more sure it works on more compilers and I want avoid maintaining code for each such specific behavior. Also I am already using something similar libraries from Boost.

Was it helpful?

Solution

As Edward Diener, the creator of the library, informs us in this thread :

TTI cannot identify inherited member functions even if they are public.

So since you still want to use TTI, let's make a work around. I'll be using an example similar to the related manual pages in BOOST, only inheritance will be added to the 'problem' :

struct AClass { };

struct Top {
    int function1();
    AClass function2(double, short *);
};

struct Top2 : Top {
    long function2(Top &, int, bool, short, float);
    Top * function3(long, int, AClass &);
};

int main()
{
    cout << has_member_function_function1<Top, int>::value << endl;; // 1. true
    cout << has_member_function_function1<Top2, int>::value << endl; // 2. false
    return 0;
}

Case (2) is an error since a function named function1 returning an int is defined in the base class of Top2, class Top

1. Mechanism to check across a hierarchy of classes

First step will be to build a mechanism that would apply TTI checks to an arbitrary number of classes :

template <
    template <class, class, class, class> class check,
    typename Ret, typename... Bases
>
struct has_m_f;


template < 
    template <class, class, class, class> class check, 
    typename Ret, typename Base
>
struct has_m_f <check, Ret, Base>
{
    static const bool value = check<Base, Ret, 
        boost::mpl::vector<>, boost::function_types::null_tag>::value;
};


template < 
    template <class, class, class, class> class check, 
    typename Ret, typename Base, typename... Bases
>
struct has_m_f <check, Ret, Base, Bases...>
{
    static const bool value = check<Base, Ret, 
        boost::mpl::vector<>, boost::function_types::null_tag>::value 
        || has_m_f<check, Ret, Bases...>::value;
};

has_m_f is a struct that forwards an arbitrary length of classes to has_member_function_... structs, which will be doing the check. No algorithm is added, just a mechanism to elevate the predicate using existential quantification :

if any of the classes ascending the hierarchy has such a member function then return true

With this tool, in your case, you could write

has_m_f < has_member_function_function1, int, Top2, Top >::value;

The template arguments are :

  1. The struct that checks for the member function (eg has_member_function_function2)
  2. The return type of the function
  3. Arbitrary number of classes in the hierarchy

2. Auto producing the base classes

The above workaround suffers from the fact that you have to manually supply the base classes. When practicing generic programming, being specific is a drawback.

A way to have this kind of introspection is through std::tr2::bases. If you have an implementation that supports it (it's going to be standard in a "while") you can at last have your introspection using TTI :

has_m_f < has_member_function_function1, int, Top2,
            std::tr2::bases<Top2>::type >::value;

HTH

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top