Ihre Überladung bleibt mehrdeutig (Art von), aber auf dem Weg zur Feststellung, dass Ihr Code in einem harten Fehler beim Ausprobieren der beiden Möglichkeiten (Übergabe eines int oder einer Zeichenfolge) läuft.
Um die Ambiguität zu sehen, fügen Sie Ihrem Lambda ein ->bool
hinzu, damit es den Körper nicht kompilieren muss, um den Rückgabewert zu bestimmen.
Der Körper eines Lambda befindet sich nicht in einem Bereich, in dem ein Substitutionsfehler nicht zu einem Fehler führt. Stattdessen erhalten Sie dort einen schweren Fehler.
Die einfache Lösung besteht darin, dass Ihr Lambda explizit einen int-Wert annimmt.
Wenn Sie eine generische Lösung:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...) \
[](auto&&...args) \
RETURNS(__VA_ARGS__(decltype(args)(args)...))
und dann
invok(OVERLOADS_OF(test));
hat (zumindest näher an) das Richtige.
Dieses Makro verschiebt den Fehler vom Körper des Lambda in einen nachfolgenden Rückgabetyp. Und der Fehler (dieser String kann nicht zum Test übergeben werden) tritt jetzt in einem Kontext auf, in dem Substitutionsfehler keinen Fehler verursacht (SFINAE). So funktioniert alles.
Die genauen Regeln für was ist SFINAE freundlich und was nicht benötigt, den Standard zu lesen. Die Faustregel lautet jedoch, dass es gut funktioniert, dass Compiler Fehler in Funktionskörpern nicht als Substitutionsfehler behandeln müssen und dass der Zugriff auf den Inhalt einer nicht definierten Klasse ein schwerer Fehler ist.Das erste, weil es ein vernünftiger Ort zu sein schien, eine Linie zu zeichnen und es für Compiler-Schreiber leichter zu machen; der zweite, weil die Alternative Wahnsinn oder ODR Bug Köder ist.
In der Praxis sind die Regeln der SFINAE-Regeln arkaner, und zuletzt habe ich in C++ 14 nachgeprüft, dass SFINAE während der partiellen Spezialisierung der Template-Klasse weggelassen wurde: Jeder Compiler hat es unterstützt. Aber vielleicht habe ich es falsch verstanden. In jedem Fall scheint die von mir verwendete Faustregel genauso nützlich zu sein wie der Standardtext. Beide werden nicht perfekt sein.
Ah, SFINAE-unfreundliche generische Lambdas. –
Ich stimme dieser Frage zu. – Barry