Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specialize C++ member function based on class template argument

I have a class with a template parameter which should decide which of two styles of data it contains. Based on that parameter I want to implement a member function one of two different ways. I tried using Boost Enable-If, but without success. Here's the version of the code that I'm most surprised doesn't work:

#include <boost/utility/enable_if.hpp>
enum PadSide { Left, Right };
template <int> struct dummy { dummy(int) {} };

template <PadSide Pad>
struct String
{
    typename boost::enable_if_c<Pad ==  Left, void>::type
        getRange(dummy<0> = 0) {}
    typename boost::enable_if_c<Pad == Right, void>::type
        getRange(dummy<1> = 0) {}
};

int main()
{
    String<Left> field;
    field.getRange();
}

To this, g++ 4.6.0 says:

no type named ‘type’ in ‘struct boost::enable_if_c<false, void>’

Of course, the second overload is supposed to not work, but it's supposed to be ignored due to SFINAE. If I remove the dummy function parameters, g++ says this:

‘typename boost::enable_if_c<(Pad == Right), void>::type
    String<Pad>::getRange()‘
cannot be overloaded with
‘typename boost::enable_if_c<(Pad == Left), void>::type
    String<Pad>::getRange()‘

Which is why I put the dummy parameters there in the first place--following the Compiler Workarounds section of the documentation.

Basically what I want is to have two implementations of getRange(), and have one or the other be selected based on the Pad type. I was hoping that Enable-If would let me do it without making auxiliary classes to delegate the work to (which I'm going to try in the meantime).

like image 398
John Zwinck Avatar asked Jul 14 '11 15:07

John Zwinck


1 Answers

Since you are going to be making two different versions of getRange() anyways, you can always overload your struct String member functions depending on the type of PadSide. I know it's not as "pretty", but in the end, it's still a similar amount of code, and you won't have to make multiple class types.

template<PadSide Pad>
struct String
{
    void getRange();
};

template<>
void String<Right>::getRange() { /*....*/ }

template<>
void String<Left>::getRange() { /*....*/ }
like image 132
Jason Avatar answered Sep 30 '22 06:09

Jason