Подтвердить что ты не робот

Специализация по целым диапазонам

Я пытался получить специализацию на основе целочисленного значения в качестве типа шаблона. Если я использую одно целое число, специализация прямолинейна. Возможно ли иметь специальную специализацию по шаблону, основанную на диапазоне без использования форсированного фундамента.

Этот репрезентативный код переводит на

template <typename int val>
class Param
{
public:

};

template <> class Param<0 to 100>
{

};

template <> class Param<100 to 175>
{

};
4b9b3361

Ответ 1

Вот один (простой) способ реализовать ваши требования, используя SFINAE:

template<bool> struct Range;

template<int val, typename = Range<true> >
class Param
{};

template<int val>
class Param<val, Range<(0 <= val && val <= 100)> >
{};

template<int val>
class Param<val, Range<(100 < val && val <= 175)> >
{};

Демо.

Ответ 2

Вы можете использовать SFINAE с помощью std::enable_if, чтобы создать свой собственный класс тестирования диапазона времени компиляции:

#include <iostream>
#include <type_traits>

using namespace std;

template<int Start, int End, int Val, class Enable = void>
struct crange { };

template<int Start, int End, int Val>
struct crange<Start, End, Val, typename std::enable_if<Val >= Start && Val <= End>::type> {
    typedef void enabled;
};

template<int Val, class Enable = void>
class Param {
public:
    Param() : value(422) { }

    int value;
};

template<int Val>             // V  VV the range [x, y]
class Param<Val, typename crange<0, 10, Val>::enabled> {
public:
    Param() : value(1.32) { }

    double value;
};

int main() {
    Param<1> pdouble;
    Param<50> pint;

    cout << pdouble.value << endl; // prints 1.32
    cout << pint.value    << endl; // prints 422
}

Ответ 3

Возможно ли иметь простую специализированную специализацию на основе диапазона без использования форсированного фундамента.

Не для С++ 03 в очень изящном, сжатом, обслуживаемом и общем способе, где можно легко указать достаточно большие диапазоны. Чтобы код был кратким, вам понадобится что-то вроде библиотеки препроцессора boost, чтобы перебрать диапазон значений.

Без BOOST или переопределяя огромные куски, вы можете создать несколько грустных маленьких макросов, чтобы вызвать исходный макрос для определенного количества последовательных значений. Например:

#define X(N) template <> class Param<N> { ... };
#define X2(N) X(N) X(N+1)
#define X4(N) X2(N) X2(N+2)
#define X8(N) X4(N) X4(N+4)
...

// template <> class Param<100 to 175> then becomes
X64(100); // 100..163
X8(164);  // 164..171
X4(172);  // 172..175

В качестве альтернативы вы можете использовать программу / script для написания кода на С++, как более ранний шаг компиляции, иногда это получается лучше - иногда хуже - чем препроцессорный хакер.