2012-01-14 6 views
6

¿Hay algún truco sutil para la especialización de plantillas para poder aplicar una especialización a basic POD? (Cuando digo POD básico, no quiero particularmente struct POD (pero lo tomaré)).Especialización de plantillas para POD básico solo

template<typename T> 
struct DoStuff 
{ 
    void operator()() { std::cout << "Generic\n";} 
}; 
template<> 
struct DoStuff</*SOme Magic*/> 
{ 
    void operator()() { std::cout << "POD Type\n";} 
}; 

¿O tengo que escribir especializaciones para cada uno de los tipos incorporados?

template<typename T> 
struct DoStuff 
{ 
    void operator()() { std::cout << "Generic\n";} 
}; 


// Repeat the following template for each of 
// unsigned long long, unsigned long, unsigned int, unsigned short, unsigned char 
//   long long,   long,   int,   short, signed char 
// long double, double, float, bool 
// Did I forget anything? 
// 
// Is char covered by unsigned/signed char or do I need a specialization for that? 
template<> 
struct DoStuff<int> 
{ 
    void operator()() { std::cout << "POD Type\n";} 
}; 

Unit Test.

int main() 
{ 
    DoStuff<int>   intStuff; 
    intStuff();   // Print POD Type 


    DoStuff<std::string> strStuff; 
    strStuff();   // Print Generic 
} 
+0

Ok, tengo curiosidad - ¿Qué tipo de "cosas" desea hacer que la implementación ya no sea diferente para los tipos de POD? –

+0

Estoy usando boost :: mpl. Para objetos de clase, necesito registrar una acción que manipule el objeto de clase (y registrar acciones para todos sus miembros). Para objetos POD normales, tengo una acción mucho más simple que se registrará para realizar la acción en el objeto. –

Respuesta

6

Si realmente quiere sólo los tipos fundamentales y no definidos por el usuario tipos de POD entonces el siguiente debe funcionar:

#include <iostream> 
#include <boost/type_traits/integral_constant.hpp> 
#include <boost/type_traits/is_fundamental.hpp> 
#include <boost/type_traits/is_same.hpp> 

template<typename T> 
struct non_void_fundamental : boost::integral_constant< 
    bool, 
    boost::is_fundamental<T>::value && !boost::is_same<T, void>::value 
> 
{ }; 

template<typename T, bool Enable = non_void_fundamental<T>::value> 
struct DoStuff 
{ 
    void operator()() { std::cout << "Generic\n"; } const 
}; 

template<> 
struct DoStuff<T, true> 
{ 
    void operator()() { std::cout << "POD Type\n"; } const 
}; 

Si también desea POD tipos definidos por el usuario, a continuación, utilizar boost::is_pod<> en lugar de non_void_fundamental<> (y si estás usando C++ 11 y hacer esto con fines de optimización, el uso std::is_trivially_copyable<> en su lugar).

1

Boost tiene boost::is_pod. ¿Es eso lo que estás buscando?

(nunca he usado, así que no voy a avergonzarme por tratar de formular el código precisa que se requiere para su ejemplo.)

+1

C++ 11 también tiene esto. –

6

En C++ 11, se han agregado muchos rasgos a la biblioteca estándar, y la mayoría parecen particularmente dirigidos hacia especializaciones interesantes (y notablemente a manipulaciones bit a bit).

El rasgo de alto nivel que podría estar interesado en es std::is_trivial, sin embargo, hay muchos otros:

  • std::is_trivially_default_constructible
  • std::is_trivially_copy_constructible
  • std::is_trivially_move_constructible
  • std::is_trivially_copyable (se pueden copiar a través de memcpy)

En general, el estándar ha tratado de obtener rasgos lo más finos posibles, por lo que no necesita confiar en suposiciones tan amplias como is_pod, sino que ajusta sus restricciones para que coincidan con lo que sus métodos realmente necesitan.

Cuestiones relacionadas