Специализировать функцию-член C ++ на основе аргумента шаблона класса - PullRequest
5 голосов
/ 14 июля 2011

У меня есть класс с параметром шаблона, который должен решить, какой из двух стилей данных он содержит.Основываясь на этом параметре, я хочу реализовать функцию-член одним из двух разных способов.Я пытался использовать Boost Enable-If, но безуспешно.Вот версия кода, которая меня больше всего удивляет, не работает:

#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();
}

Для этого g ++ 4.6.0 говорит:

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

Конечно, вторая перегрузкадолжен не работать, но это должно быть проигнорировано из-за SFINAE.Если я удаляю параметры фиктивной функции, g ++ говорит следующее:

‘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()‘

Именно поэтому я ставлю фиктивные параметры там в первую очередь - следуя разделу Обходные пути компилятора Документация .

По сути, мне нужно иметь две реализации getRange () и выбирать одну или другую в зависимости от типа Pad.Я надеялся, что Enable-If позволит мне сделать это без создания вспомогательных классов для делегирования работы (которую я собираюсь попробовать в это время).

1 Ответ

7 голосов
/ 14 июля 2011

Так как вы собираетесь делать две разные версии getRange() в любом случае, вы всегда можете перегрузить свои struct String функции-члены в зависимости от типа PadSide.Я знаю, что это не так «красиво», но, в конце концов, это все тот же объем кода, и вам не придется создавать несколько типов классов.

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

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

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