2013-05-18 12 views
5

jak byś poszperał przy użyciu porównywania parametrów szablonów nie typu w std::enable_if? Nie mogę wymyślić, jak to zrobić ponownie. (Kiedyś to działało, ale zgubiłem kod, więc nie mogę na nie spojrzeć i nie mogę znaleźć wpisu, na który znalazłem odpowiedź.)std :: enable_if Z parametrami szablonu bez szablonu

Z góry dziękujemy za pomoc ten temat.

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: Poprawiono brakujący nawias jak wskazano w komentarzach.

+3

Prawdopodobnie użyłbym 'static_assert' do tego. Zapewnia wyraźne komunikaty o błędach. – chris

+0

'static_assert' jest właściwym narzędziem:' std :: enable_if' jest dla SFINAE i nie ma możliwości SFINAE dla elementu szablonu szablonu, który nie jest szablonem. –

+0

Myślałem o użyciu 'static_assert', ostatecznie mogę skończyć się go używać. Ale robiłem to już wcześniej i z przewagą funkcji automatycznego uzupełniania, nie wymieniając nawet funkcji macierzy innych niż kwadratowe. W dużej mierze w tym momencie próbuje dowiedzieć się, jak to kiedyś zrobiłem, używając 'std :: enable_if'. – LostOfThought

Odpowiedz

3

Wszystko zależy od rodzaju błędu/niepowodzenia, które chcesz podnieść na nieprawidłowym kodzie. Tutaj jest to jedna z możliwości (pomijając oczywiste static_assert(Width==Height, "not square matrix");)

(C++ 98 styl)

#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: W C++ 11 kod może być bardziej zwarty i przejrzysty, (to pracuje w clang 3.2 ale nie w gcc 4.7.1, więc nie jestem pewien, jak to jest norma):

(C++ 11 styl)

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

Po prostu pokonaj mnie, kończąc moją własną odpowiedź na pytanie. Dziękuję za odpowiedź niezależnie. Oznaczono jako zaakceptowany. – LostOfThought

+1

W wersji C++ 11 istnieje bardziej kompaktowa alternatywa: 'template :: type> static Matrix Identity() {... } ' – alfC

+0

Czy' WDummy' jest potrzebne? MSVC: CTP Nov'12 z kompilacją/W4 bez problemu. – LostOfThought

1

Znalazłem odpowiedź na moje pytanie tutaj: Using C++11 std::enable_if to enable...

W moim rozwiązaniu SFINAE występuje w ramach szablonu typu szablonowego, dlatego też sam szablon funkcji jest ważny. W trakcie tego sama funkcja również staje się szablonem.

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

Dodałem bardziej kompaktową wersję w moja odpowiedź, ale nie działa w 'gcc'. BTW, "typename" przed 'Matrix' jest w najlepszym razie nadmiarowe. – alfC

+0

Kod w edytorze jest taki sam jak w mojej nowej odpowiedzi, nie ma sensu go tutaj powtarzać. – alfC

+0

Widzę to teraz. Nie był przeznaczony. Przez całą noc ingerowałem w ten kod, naprawdę jestem tym znudzony. Niezależnie od tego, dziękuję za pomoc. – LostOfThought

Powiązane problemy