2012-01-14 14 views
6

Esiste un sottile trucco per la specializzazione dei modelli in modo che io possa applicare una specializzazione a basic POD (quando dico POD di base non desidero particolarmente struct POD (ma lo prenderò)).Template Specialization for basic POD only

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

Oppure devo scrivere specializzazioni per ciascuno dei tipi integrati?

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";} 
}; 

Test unità.

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


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

Ok, sono curioso - Che tipo di "roba" vuoi fare che l'implementazione non faccia già in modo diverso per i tipi di POD? –

+0

Sto usando boost :: mpl. Per oggetti di classe ho bisogno di registrare un'azione che manipola l'oggetto classe (e registra le azioni per tutti i suoi membri). Per gli oggetti POD normali ho un'azione molto più semplice che verrà registrata per eseguire l'azione sull'oggetto. –

risposta

6

Se si vuole veramente solo con tipi fondamentali e non definite dall'utente tipi POD poi il seguente dovrebbe funzionare:

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

Se anche voi volete tipi POD definiti dall'utente, quindi utilizzare boost::is_pod<> invece di non_void_fundamental<> (e se si sta utilizzando C++ 11 e facendo questo per scopi di ottimizzazione, utilizzo std::is_trivially_copyable<> invece).

1

Boost ha boost::is_pod. E 'quello che stai cercando?

(non l'ho mai usato, quindi non voglio mettere in imbarazzo me stesso, cercando di formulare il codice preciso che si richiedono per il tuo esempio.)

+1

C++ 11 ha anche questo. –

6

In C++ 11, molti tratti sono stati aggiunti alla libreria standard e la maggior parte sembra particolarmente indirizzata verso specializzazioni interessanti (e in particolare manipolazioni bit a bit).

Il tratto di alto livello che potrebbe interessare è std::is_trivial, tuttavia ci sono molti altri:

  • std::is_trivially_default_constructible
  • std::is_trivially_copy_constructible
  • std::is_trivially_move_constructible
  • std::is_trivially_copyable (possono essere copiati tramite memcpy)

In generale, lo standard ha cercato di ottenere i caratteri più fini possibili, quindi non è necessario fare affidamento su presupposti così ampi come is_pod, ma invece perfezionare i vincoli in modo che corrispondano a ciò di cui i metodi sono realmente necessari.