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 derstd::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; }
Habt Ihr ne Idee, wie man es vielleicht doch testen könnte?
-
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)
-
// should return 'false', but actually returns 'true'
Der
operator==
vonvector
wendet nicht selbst SFINAE an, kann also lediglich einen hard error liefern. Du musst schon für denvalue_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.
-
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.