Search code examples
c++templatesboostsfinaeenable-if

Unable to specialize a member function template with boost::enable_if in VS .NET 2008


I'm trying to specialize a member function template for two different types of classes as follows:

#include <iostream>
#include <boost/utility/enable_if.hpp>

struct Wibble
{
    static const bool CAN_WIBBLE = true;
};

struct Wobble
{
    static const bool CAN_WIBBLE = false;
};

struct Foo
{
    //template<typename T>   // Why isn't this declaration sufficient?
    //void doStuff();

    template<typename T>
    typename boost::enable_if_c<T::CAN_WIBBLE,void>::type
    doStuff();

    template<typename T>
    typename boost::enable_if_c<!T::CAN_WIBBLE,void>::type
    doStuff();  
};

template<typename T>
typename boost::enable_if_c<T::CAN_WIBBLE,void>::type
Foo::doStuff()
{
    std::cout << "wibble ..." << std::endl;
}

template<typename T>
typename boost::enable_if_c<!T::CAN_WIBBLE,void>::type
Foo::doStuff()
{
    std::cout << "I can't wibble ..." << std::endl;
}

int main()
{
    Foo f;
    f.doStuff<Wibble>();
    f.doStuff<Wobble>();
}

Whereas GCC 4.8.2 compiles the code, VS .NET 2008 spits out the error message:

error C2244: 'Foo::doStuff' : unable to match function definition to an existing declaration

        definition
        'boost::enable_if_c<!T::CAN_WIBBLE,void>::type Foo::doStuff(void)'
        existing declarations
        'boost::enable_if_c<!T::CAN_WIBBLE,void>::type Foo::doStuff(void)'
        'boost::enable_if_c<T::CAN_WIBBLE,void>::type Foo::doStuff(void)'

Solution

  • I suggest to use tag dispatching: https://ideone.com/PA5PTg

    struct Foo
    {
        template<bool wibble>
        void _doStuff();
    
    public:
        template<typename T>
        void doStuff()
        {
            _doStuff<T::CAN_WIBBLE>();
        }
    };
    
    template<>
    void Foo::_doStuff<true>() { std::cout << "wibble ..." << std::endl; }
    
    template<>
    void Foo::_doStuff<false>() { std::cout << "I can't wibble ..." << std::endl; }