5

Co jest lepsze (jeśli jest)?Barton-Nackman kontra std :: enable_if

Wariant A (Barton-Nackman):

template<class T> 
struct equal_comparable { 
    friend bool operator == (const T & t1, const T & t2) { 
     return t1.equalTo (t2); 
    } 
}; 

class MyClass : private equal_comparable<MyClass> { 
    bool equalTo (const MyClass & other) //... 
}; 

Wariant B (std :: enable_if):

struct MyClass { 
    static const bool use_my_equal = true; 
    bool equalTo (const MyClass & other) //... 
}; 

template<class T> 
typename std::enable_if< 
    T::use_my_equal, 
    bool 
>::type 
operator == (const T & t1, const T & t2) { return t1.equalTo (t2); } 
+0

Osobiście wolę ten pierwszy. 'equal_comparable' może zostać umieszczony w odpowiedniej przestrzeni nazw, ale kto wie, do czego służy element' use_my_equal' przez jakiś typ 'T', o którym nigdy nie słyszałeś. Oczywiście ten problem dotyczy innych podobnych zastosowań 'enable_if' - tylko dlatego, że nazwa zależna rozwiązuje, niekoniecznie * oznacza, że ​​nazwa jest używana dla tego, co Twoim zdaniem oznacza, jeśli usuwasz ją z przestrzeni nazw nie kontroluj. Zamiast tego możesz użyć cechy typu. –

+0

Dlaczego warto korzystać z szablonu? Dlaczego nie po prostu 'operator bool == (const MyClass &,/* etc * /) ;?' – GManNickG

+0

@GManNickG: Uważam, że celem tej sztuczki jest zmniejszenie wymaganej dla każdej klasy skali, która jest porównywalna pod względem równości. –

Odpowiedz

4

wolałbym używać Boost.Operators wspomniany przez @SteveJessop w komentarzach, które formalizuje i automatyzuje twoje pierwsze podejście. Zajmują się również pustą optymalizacją bazy, jeśli potrzebujesz wielu zestawów operatorów (a zatem potrzebują wielokrotnego dziedziczenia). To nie tyle oszczędności w pisaniu, ale także dokumentacja kodu/wartość egzekwowania, ponieważ te klasy baz są na samym początku interfejsu klasy. W tym sensie jest to prymitywny sposób pojęć.

Powiązane problemy