Implementierung von is_callable
-
std::is_class<T>::value, // false für unions und unspezifiziert (?) für Lambdasclosure types sind Klassen.
-
ungestet, evtl. Denkfehler drin.
Neben falschem Rueckgabetyp ein peinlicher Fluechtigkeitsfehler
[temp.arg.nontype]/5 schrieb:
For a non-type template-parameter of integral or enumeration type, conversions permitted in a converted constant expression (5.19) are applied.
[expr.const]/3 schrieb:
A converted constant expression of type
Tis a literal constant expression, implicitly converted to typeT, where the implicit conversion (if any) is permitted in a literal constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (4.1), integral promotions (4.5), and integral conversions (4.7) other than narrowing conversions (8.5.4).Boolean conversions sind nicht beinhaltet, daher muss da noch ein Cast hin.
-
Arcoth schrieb:
ungestet, evtl. Denkfehler drin.
Neben falschem Rueckgabetyp ein peinlicher Fluechtigkeitsfehler
Besonders peinlich ist mir das nicht

und wieso falscher Rückgabetyp?Vergleich != nullptr fände ich and dieser Stelle schöner als einen expliten Cast.
-
Ich wusste bloss, dass der Standard zu Closures nicht sonderlich viel sagt.
Doch, der sagt darueber sogar sehr, sehr viel.
und wieso falscher Rückgabetyp?
Warum gibst du "Nein" zurueck wenn die Klasse callable ist?
camper schrieb:
Besonders peinlich ist mir das nicht

Scheisse, du bist so cool

Vergleich != nullptr fände ich and dieser Stelle schöner als einen expliten Cast.
Und ich faende ein Klassentemplate sowieso passender, aber
template<typename C, void* = &C::operator()> static yes test(int);geht auch
Edit: Nein, geht natuerlich nicht.
-
Das kuerzeste ist wahrscheinlich
template<typename C, int = sizeof(&C::operator())> static yes test(int);
-
Arcoth schrieb:
Warum gibst du "Nein" zurueck wenn die Klasse callable ist?
Tue ich doch nicht. Ich gebe nein zurück, weil der Memberzeiger &C::operator() formbar ist, was Eindeutigkeit voraussetzt. Die ist nur gegeben, falls der aus Fallback geerbte Operator der Einzige ist, also nichts aus T geerbt wurde. Wurde nichts aus T geerbt, ist T offenbar nicht callable...
-
Ah, ich haette vielleicht den Code lesen sollen anstatt anzunehmen dass es nur unnoetiger Boilerplaite ist...
-
Danke für eure Antworten un euer Interesse.
Der Hinweis zu dem Methodenzeiger und R-Value war hilfreich :).
Für unions habt ihr natürlich recht, man vergisst doch immer wieder einen Randfall ;). Allerdings können unions keine Basisklasse aufweisen. Da müsste man sich etwas anderes ausdenken.Ich würde gerne noch auf diese Variante zu sprechen kommen, wo wahrscheinlich bei mir ein Denkfehler liegt.
template<typename C, class R = typename std::conditional<std::is_same<void(Fallback::*)(), decltype(&C::operator())>::value, no, yes >::type> static R test(...);Warum ist das nicht möglich?
-
Na weil, falls die Klasse die der Templateparameter bezeichnet einen `operator()` hat, der Ausdruck
&C::operator()ill-formed ist (weil dann mehrere operator()s in Derives Scope sind). Genau dass ist ja der Trick, und deswegen ueberlaedt man mit SFINAE.
-
Mark2015 schrieb:
Ich würde gerne noch auf diese Variante zu sprechen kommen, wo wahrscheinlich bei mir ein Denkfehler liegt.
template<typename C, class R = typename std::conditional<std::is_same<void(Fallback::*)(), decltype(&C::operator())>::value, no, yes >::type> static R test(...);Warum ist das nicht möglich?
Weil der is_same-Test nicht das testet, worauf es ankommt. Eigentlich habe ich das schon weiter oben beantwortet.
Nebenbei: als ich den Code das Erste mal gelesen hatte, musste ich erst mal nachschlagen, wieso der funktioniert. War mir nicht bewusst, dass der Typ von &C::member tatsächlich irgendein
T B::* ist, falls member aus B geerbt wurde.
-
Alles klar, mein Denkfehler wird mir jetzt klar. Ich hatte fälschlicherweise angenommen, dass wie in manch anderer Sprache implizit die Mehrdeutigkeit aufgelöst wird für Operatoren. Mir war zwar bewusst, dass dies für Funktionen gilt, jedoch nicht, dass dies auch für Operatoren gilt. Eine Art die Mehrdeutigkeit aufzulösen, ist die Basisklassen zu ordnen, sodass die erste Klasse bei Mehrdeutigkeit die höchste Priorität hat.