2010-08-11 14 views
6

En la descripción de alguna función de plantilla std vi algo como:¿Cómo verificar que el tipo de parámetro de la plantilla sea integral?

si el parámetro de plantilla es de tipo integral, el comportamiento es tal y tal.
de lo contrario, es tal y tal.

¿Cómo puedo hacer una prueba similar? Quizás dynamic_cast?

Dado que la función que escribo es para mi uso personal, puedo confiar en mí solo para proporcionar los parámetros correctos, pero ¿por qué perder la oportunidad de aprender algo? :)

Respuesta

4

Además de las otras respuestas, debe tenerse en cuenta que la prueba se puede utilizar en tiempo de ejecución, sino también en tiempo de compilación para seleccionar la aplicación correcta dependiendo de carnero el tipo es integral o no:

versión

tiempo de ejecución :

// Include either <boost/type_traits/is_integral.hpp> (if using Boost) 
// or <type_traits> (if using c++1x) 
// In the following, is_integral shoudl be prefixed by either boost:: or std:: 

template <typename T> 
void algorithm(const T & t) 
{ 
    // some code 

    if (is_integral<T>::value) 
    { 
     // operations to perform if T is an integral type 
    } 
    else 
    { 
     // operations to perform if T is not an integral type 
    } 

    // some other code 
} 

Sin embargo, esta solución se puede mejorar cuando la implementación del algoritmo depende en gran medida de la prueba. En este caso, tendríamos la prueba en la parte superior de la función, luego un gran bloque then y un gran bloque else. Un enfoque común en este caso es sobrecargar la función y hacer que el compilador seleccione la implementación correcta utilizando SFINAE. Una manera fácil de hacer esto es utilizar boost::enable_if:

#include <boost/utility/enable_if.hpp> 
#include <boost/type_traits/is_integral.hpp> 

template <typename T> 
typename boost::enable_if<boost::is_integral<T> >::type 
algorithm(const T & t) 
{ 
    // implementation for integral types 
} 

template <typename T> 
typename boost::disable_if<boost::is_integral<T> >::type 
algorithm(const T & t) 
{ 
    // implementation for non integral types 
} 

Cuando se invoca la función algorithm, el compilador "seleccionar" a la aplicación correcta en función de carnero el parámetro de plantilla es integral o no.

+0

muy útil, gracias – davka

+0

Diría que cada compilador que valga su grano eliminará la rama muerta en su primer ejemplo, es bastante simple. –

+1

@Georg Fritzsche: esto es cierto, es por eso que no dije nada sobre un posible aumento de rendimiento. Sin embargo, creo que el enfoque de sobrecarga es más claro: las dos implementaciones pueden evolucionar por separado, y me pareció mejor discriminar entre lo que es estático (conocido/ejecutado en tiempo de compilación) y lo que es dinámico (conocido/ejecutado en tiempo de ejecución). Pero bueno, eso puede deberse a que pasé demasiado tiempo haciendo metaprogramación en los últimos meses. –

3

One possibility:

#include <type_traits> 
#include <iostream> 

struct trivial 
{ 
    int val; 
}; 

int main() 
{ 
    std::cout << "is_integral<trivial> == " << std::boolalpha 
     << std::is_integral<trivial>::value << std::endl; 
    std::cout << "is_integral<int> == " << std::boolalpha 
     << std::is_integral<int>::value << std::endl; 
    std::cout << "is_integral<float> == " << std::boolalpha 
     << std::is_integral<float>::value << std::endl; 

    return (0); 
} 

Así que posteriormente utiliza std::is_integral<> para determinar la acción.

1

Boost.TypeTraits proporciona is_integral <>(), como se describe en otra respuesta, si su compilador aún no admite las características de C++ del siguiente estándar.

+0

probablemente no, acabo de comprobar que no tengo el archivo de inclusión type_traits. debería haber agregado etiquetas 'linux' y 'gcc' ... – davka

+0

@davka: Esas etiquetas no tienen nada que ver con el impulso. Si falta el encabezado, debe agregar la ubicación correcta a la ruta de búsqueda para encabezados o aumentar la instalación. –

Cuestiones relacionadas