SFINAE um zu testen ob operator "==" von klassen template wirklich nutzbar ist



  • Hi zusammen,

    ist es mit SFINAE möglich zu testen ob der call zum == operator eines Klassen templates möglich ist?
    Als Beispiel soll der std::vector<T> herhalten.

    Wenn ein type T für std::vector<T> verwendet wird, so muss dieser Typ T nicht den "==" operator definieren, nur wenn beim vector wirklich den code für "==" instantiert.

    Hier ist mein Ansatz, er funktioniert leider nicht für klassen templates.

    #include <iostream>
    #include <type_traits>
    #include <vector>
    
    using namespace std;
    
    template<typename T, typename = decltype(std::declval<T>() == std::declval<T>() )> 
    std::true_type  supports_euqla_test(const T&);
    std::false_type supports_euqla_test(...);
    
    template<typename T>
    struct can_use_equal_operator : std::integral_constant<bool, std::is_same<std::true_type, 
                                                                 decltype(supports_euqla_test(std::declval<T>()))>::value> {};
    
    struct foo
    {
    };
    
    int main() {
    	std::vector<foo> obj;
    	std::cout << std::boolalpha << 
    				can_use_equal_operator<decltype(obj)>::value << std::endl; // should return 'false', but actually returns 'true'
    	//std::cout << (obj == obj) << std::endl; // compile error
    	return 0;
    }
    

    http://ideone.com/lqDfmn

    Habt Ihr ne Idee, wie man es vielleicht doch testen könnte?


  • Mod

    template <typename, typename=bool> struct EqualityComparable : std::false_type{};
    template <typename T> struct EqualityComparable<T, decltype(bool(std::declval<T const&>() == std::declval<T const&>()))> : std::true_type{};
    

    (ungetestet)
    Oder, mittels concepts:

    template <typename T>
    concept bool EqualityComparable = requires (T const a, T const b) {{a == b} -> bool;}
    

    (ebenfalls ungetestet)


  • Mod

    // should return 'false', but actually returns 'true'

    Der operator== von vector wendet nicht selbst SFINAE an, kann also lediglich einen hard error liefern. Du musst schon für den value_type testen.



  • das mit std::vector<T> ist nur ein Beispiel, mir geht es um eine generelle Lösung für alle template typen.
    Kann ich mit SFINAE feststellen ob der Aufruf zu einem operator (bsp. "==") möglich ist oder nicht.



  • Hallo

    Wie Arcoth schon gesagt hat, ist dein Problem, dass du den Typ Vector prüfst ob er den ==-Operator besitzt. In deinem Fall müsstest du aber vector<T>::value_type prüfen.

    Grus Marco



  • Nun ja, eigentlich wird geprüft ob der call zu

    std::declval<T>() == std::declval<T>()
    

    möglich ist.

    Das sind also die grenzen von SFINAE, es gibt keine Möglichkeit zu überprüfen ob ein call zu einem Klassen template möglich ist.


  • Mod

    Nash26 schrieb:

    Das sind also die grenzen von SFINAE, es gibt keine Möglichkeit zu überprüfen ob ein call zu einem Klassen template möglich ist.

    Unsinn. Lies doch mal meine zweite Antwort.



  • Selbstverständlich habe ich Deine Antwort gelesen.
    Nur leider hast du das Problem in seiner Gänze noch nicht verstanden.
    Ich will eine generelle Lösung, std::vector<T> war nur Beispielhaft genommen.

    Was ist wenn ich überprüfen will ob eine X-Beliebiges Klassen template den "==" operator unterstützt und das natürlich kein typedef value_type definiert hat. Ich will keine zig Spezialisierungen schreiben, ich will schlicht und einfach überprüfen ob der Vergleich eines Beliebigen types möglich ist oder nicht.



  • Der von Arcoth gezeigte Code überprüft, ob es eine Deklaration eins operator== gibt (und dieser Aufruf nicht via SFINAE deaktiviert ist). Sie überprüft nicht, ob es eine Definition gibt, oder ob die Definition kompiliert. So etwas kann SFINAE nicht.

    Deshalb funktioniert std::vector<T> auch nicht. std::vector hat immer einen operator==, unabhäng davon ob T einen hat. Deshalb gibt es immer eine gültige Dekleration, weswegen man das so nicht überprüfen kann.



  • Nash26 schrieb:

    Das sind also die grenzen von SFINAE, es gibt keine Möglichkeit zu überprüfen ob ein call zu einem Klassen template möglich ist.

    Ähm, wenn eine Klasse behauptet, den op== zu haben, ohne ihn zu haben…
    Das sind nicht bloß die Grenzen von SFINAE, sondern das sind die Grenzen aller Programmiersprachen überhaupt. Sie können halt nicht perfekt mit Programmierern zusammenarbeiten, die den Compiler/Interpreter anlügen.


Log in to reply