Search code examples
c++boostoperator-keywordsfinaeenable-if

Couldn't match the template method using boost enable_if


#include <boost/type_traits.hpp>
#include <boost/utility.hpp>

using namespace boost;

struct Serializable{};

struct Derived : Serializable {};

class Serializer
{
public:
    template <typename ValueType>
    void operator& (const typename enable_if<is_base_of<Serializable, ValueType>, ValueType>::type& value) {
        ;
    }
};

int main() {
    Serializer serializer;
    Derived tar;

    serializer & tar;

    return 0;
}

I was using g++4.4.7 which gave me a compile error: error: no match for ‘operator&’ in ‘serializer & tar’

How to make the specialization happen?


Solution

  • The right-side value of the operator & should be of type ValueType. So, make the enable_if part a (fake) result type:

    #include <boost/type_traits.hpp>
    #include <boost/utility.hpp>
    
    using namespace boost;
    
    struct Serializable{};
    
    struct Derived : Serializable {};
    
    class Serializer
    {
    public:
        template <typename ValueType>
        const typename enable_if<is_base_of<Serializable, ValueType>, ValueType>::type* operator& (ValueType &v)
        {
          return 0;
        }
    };
    
    int main() 
    {
        Serializer serializer;
        Derived tar;
        int i = 1;
    
        serializer & tar; //ok
        serializer & i; //error
    
        return 0;
    }
    

    In C++11 you could also make the enable_if construct a default template parameter, which would leave the function signature clean and unmodified:

    template <typename ValueType, typename = typename enable_if<is_base_of<Serializable, ValueType>, ValueType>::type>
    void operator& (ValueType &v)
    {
    }