2016-03-13 18 views
8

Ho una classe per descrivere alcuni tratti di un tipo.Specialized data member statico constexpr

template<typename T> 
struct my_traits 
{ 
    static constexpr int some_trait = 0; 

    static constexpr T min() { return std::numeric_limtis<T>::min(); } 
    static constexpr T max() { return std::numeric_limits<T>::max(); } 
}; 

voglio specializzarmi my_traits::some_trait ma quando provo:

template<> constexpr int my_traits<int>::some_trait = 1; 

Il compilatore si lamenta che my_traits::some_trait ha già un inizializzatore. Certo che posso specializzarla facendo:

template<> 
struct my_traits<int> 
{ 
    static constexpr int some_trait = 1; 

    // min and max 
}; 

ma poi ho dovuto ridefinire tutte le altre funzioni, anche se saranno esattamente lo stesso.

Quindi, come posso specializzare my_traits<int>::some_trait senza dover ripetere min e max?

+0

AFAIK questo non è possibile. Una variabile 'constexpr' deve essere inizializzata o costruita nella sua dichiarazione. –

+6

'static constexpr int some_trait = my_helper :: value;' –

+1

Si potrebbe cercare di inizializzarlo da una funzione 'constexpr', o classe di utilità, che è specializzata per il tipo' int' – Niall

risposta

5

Ci sono diversi modi per farlo. @Piotr Skotnicki e @Niall hanno menzionato l'inizializzazione attraverso qualche aiuto che può essere specializzato. In generale, è sufficiente ristrutturare il codice in modo da poter specializzare alcune classi o funzioni e quindi utilizzare (per composizione o ereditarietà) le parti specializzate per parti che non è necessario specializzare.

Come esempio di un'alternativa ai commenti, qui è una base specializzata:

#include <iostream>                                               
#include <limits> 

template<typename T> 
struct my_specializing_traits 
{ 
    static constexpr int some_trait = 0; 
}; 

template<> 
struct my_specializing_traits<int> 
{ 
    static constexpr int some_trait = 1; 
}; 

Ora si può semplicemente sottoclasse in una parte comune:

template<typename T> 
struct my_traits : 
    public my_specializing_traits<T> 
{ 
    static constexpr T min() { return std::numeric_limits<T>::min(); } 
    static constexpr T max() { return std::numeric_limits<T>::max(); } 
}; 

Di seguito le proponiamo ha usato (emette 0 e 1)

int main() 
{ 
    std::cout << my_traits<char>().some_trait << std::endl; 
    std::cout << my_traits<int>().some_trait << std::endl; 
}