2012-03-01 19 views
13

Estaba tratando de obtener una especialización basada en el valor entero como el tipo de plantilla. Si utilizo un entero único, la especialización es directa. ¿Es posible tener una especialización de plantilla simple basada en el rango sin usar la base de refuerzo?especialización de plantilla basada en el rango entero

Esto es código representativo se traduce en

template <typename int val> 
class Param 
{ 
public: 

}; 

template <> class Param<0 to 100> 
{ 

}; 

template <> class Param<100 to 175> 
{ 

}; 

Respuesta

13

Aquí es una forma (simple) para implementar los requisitos usando 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)> > 
{}; 

Demo.

+0

Aún mejor. ¡Muchas gracias! – Ram

+0

Ah, genial. Aunque en realidad la única diferencia es que tienes que escribir '(x

+1

Es bueno que esta pregunta ahora tenga ambas formas de hacerlo para futuros visitantes. + 1 por cierto. –

-3

¿Es posible tener un simple especialización de plantilla en función del rango sin necesidad de impulso fundación.

No es para C++ 03 de una manera muy elegante, conciso, fácil de mantener y genérica, donde arbitrariamente grandes rangos se pueden especificar fácilmente. Para mantener el código conciso, necesitaría algo como la biblioteca del preprocesador de impulso para recorrer un rango de valores.

Sans BOOST o volviendo a implementar grandes cantidades de él, puede crear algunas pequeñas macros tristes para llamar a la macro inicial para un número específico de valores consecutivos. Por ejemplo:

#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 

Como alternativa, se puede usar un programa/script para escribir el código C++, como un paso de compilación anterior, a veces eso funciona mejor - a veces peor - que hackery preprocesador.

13

Puede utilizar SFINAE con std::enable_if para hacer su propia práctica en tiempo de compilación clase de pruebas de rango:

#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 
} 
+1

Seth, muchas gracias. Si hubiera una manera de marcar tu respuesta como útil varias veces, ¡haría clic en ese botón cien veces! – Ram

+2

+1 por la buena respuesta, pero es mucho más complejo de lo necesario. Ver mi respuesta – iammilind

Cuestiones relacionadas