Check also function signature for inherited functions

I need to check if the container erase function returns an iterator. I usually check the signature of a function through, for example, magnification. But in case of class promotion (like flat_set), the erasure is inherited and thus not detected by the check. But I really need it. SFINAE for checking inherited member functions only shows a C ++ 11 solution, which I can't use yet.

I've tried something like this:

    template <typename T> 
    class has_member_func_erase_it_constit
    { 
        typedef typename T::iterator iterator;
        typedef typename T::const_iterator const_iterator;
        typedef BOOST_TYPEOF_TPL(&T::erase) eraseType;

        typedef typename boost::function_types::result_type<eraseType>::type result;
    public: 
        static const bool value = boost::is_same<iterator, result>::value; 
    };

    template<class T>
    struct EraseReturnsIterator
    {
        static CONSTEXPR bool value = has_member_func_erase_it_constit<T>::value;
    };

      

But this fails because erase is overloaded. I probably need decltype or something like that to check the return type at compile time when calling erase with const_iterator, but I can't find it.

How is this possible in pre C ++ 11?

It also doesn't work if there is an erase function that returns void:

    template <typename T> 
    class has_member_func_erase_it
    { 
        typedef typename T::iterator iterator;
        typedef typename T::const_iterator const_iterator;

        typedef char yes[1];
        typedef char no [2];

        static T makeT();
        static iterator makeIt();

        typedef BOOST_TYPEOF_TPL(makeT().erase(makeIt())) result;

    public: 
        static const bool value = boost::is_same<iterator, result>::value; 
    };

      

+3


source to share


1 answer


The following works:

    /// "Stores a type"
    template<typename T> struct Type2Type{
        typedef T type;
    };

    /// Evil hackery to put an expression into a type
    template<typename T>
    Type2Type<T> operator,(T, Type2Type<void>);

    template<typename T>
    T declval();

    template<class T>
    struct EraseReturnsIterator
    {
        typedef typename T::iterator iterator;
        typedef BOOST_TYPEOF_TPL((declval<T>().erase(declval<iterator>()), Type2Type<void>())) result;

        static CONSTEXPR bool value = boost::is_same<iterator, typename result::type>::value;
    };

      

Basically, we just call a function that needs a return type. If no function of this type ever returned like BOOST_TYPEOF_TPL, it would already work. Unfortunately to erase the CAN return void, which breaks the implementation as it tries to pass "void &". somewhere down the stack.



So, to avoid the void (no pun intended), we put it in a type that contains a type. To be able to do this for expressions, we overload the comma operator. So the result is "Type2Type", which we can easily read. Done!

Idea for overloading: fooobar.com/questions/878641 / ...

0


source







All Articles