2013-05-18 12 views
5

come procedere utilizzando il confronto di parametri modello non di tipo in un std::enable_if? Non riesco a capire come farlo di nuovo. (Una volta ho funzionato, ma non riesco a trovare il post in cui ho trovato la risposta.)std :: enable_if con parametri modello non di tipo

Grazie in anticipo per qualsiasi aiuto su questo argomento.

template<int Width, int Height, typename T> 
class Matrix{ 
    static 
    typename std::enable_if<Width == Height, Matrix<Width, Height, T>>::type 
    Identity(){ 
     Matrix ret; 
     for (int y = 0; y < Width; y++){ 
      elements[y][y] = T(1); 
     } 
     return ret; 
    } 
} 

Edit: fisso staffa mancante come sottolineato nei commenti.

+3

Probabilmente userei un 'static_assert' per quello. Fornisce messaggi di errore chiari. – chris

+0

'static_assert' è davvero lo strumento giusto:' std :: enable_if' è per SFINAE e non c'è SFINAE possibile per un membro non template di un modello di classe. –

+0

Ho pensato di usare 'static_assert', in definitiva potrei finire per usarlo. Ma prima ho funzionato e, con il vantaggio dell'auto-complete, non ho nemmeno elencato la funzione per le matrici non quadrate. In gran parte a questo punto però, sta cercando di capire come ho fatto una volta questo con rigorosamente 'std :: enable_if'. – LostOfThought

risposta

3

Tutto dipende dal tipo di errore/errore che si desidera generare sul codice non valido. Qui è una possibilità (a parte l'ovvio static_assert(Width==Height, "not square matrix");) (stile C++ 98)

#include<type_traits> 
template<int Width, int Height, typename T> 
class Matrix{ 
    public: 
    template<int WDummy = Width, int HDummy = Height> 
    static typename std::enable_if<WDummy == HDummy, Matrix<Width, Height, T> >::type 
    Identity(){ 
    Matrix ret; 
    for (int y = 0; y < Width; y++){ 
    // elements[y][y] = T(1); 
     } 
     return ret; 
    } 
}; 

int main(){ 
    Matrix<5,5,double> m55; 
    Matrix<4,5,double> m45; // ok 
    Matrix<5,5, double> id55 = Matrix<5,5, double>::Identity(); // ok 
// Matrix<4,5, double> id45 = Matrix<4,5, double>::Identity(); // compilation error! 
//  and nice error: "no matching function for call to ‘Matrix<4, 5, double>::Identity()" 
} 

EDIT: In C++ 11 il codice può essere più compatto e chiaro, (esso Lavori in clang 3.2 ma non in gcc 4.7.1, quindi non sono sicuro di come normale che sia):

(C++ 11 stile)

template<int Width, int Height, typename T> 
class Matrix{ 
    public: 
     template<typename = typename std::enable_if<Width == Height>::type> 
     static Matrix<Width, Height, T> 
     Identity(){ 
     Matrix ret; 
     for (int y = 0; y < Width; y++){ 
     //  ret.elements[y][y] = T(1); 
     } 
     return ret; 
    } 
}; 
+0

Basta battermi per finire la mia risposta sulla domanda. Grazie per la risposta a prescindere. Contrassegnato come accettato. – LostOfThought

+1

In C++ 11 c'è un'alternativa più compatta: 'template :: type> static Matrix Identity() {... } ' – alfC

+0

È anche necessario' WDummy'? MSVC: CTP Nov '12 con/W4 si compila bene senza di esso. – LostOfThought

1

Ho trovato la risposta alla mia domanda qui: Using C++11 std::enable_if to enable...

Nella mia soluzione, SFINAE si verifica all'interno del mio tipo di reso a modelli, rendendo quindi valido il modello di funzione. Nel corso di questo, anche la funzione stessa diventa templata.

template<int Width, int Height, typename T> 
class Matrix{ 
    template<typename EnabledType = T> 
     static 
     typename Matrix<Width, Height, 
      typename std::enable_if<Width == Height, EnabledType>::type> 
     Identity(){ 
     Matrix ret; 
     for (int y = 0; y < Width; y++){ 
      ret.elements[y][y] = T(1); 
     } 
     return ret; 
    } 
} 
+0

Ho aggiunto una versione più compatta in la mia risposta, ma non funziona in 'gcc'. BTW, il 'typename' prima di' Matrix' è al meglio ridondante. – alfC

+0

Il codice nel tuo Modifica è lo stesso della mia nuova risposta, non ha senso ripeterlo qui. – alfC

+0

Lo vedo ora. Non era destinato Ho incasinato questo codice tutta la notte, sono davvero annoiato. In ogni caso, grazie per il tuo aiuto. – LostOfThought

Problemi correlati