Ich habe eine Funktion, die jeden Typ durch universelle Referenz akzeptieren kann, und möchte es für bestimmte Typen überladen (von denen einige selbst templates sind, obwohl ich denke, dass das hier nicht wichtig ist). Leider kann ich die Überladungen nicht in der richtigen Reihenfolge auflösen.Überladungsauflösung mit universellen Referenzen
Ich hätte angenommen, dass die zweite Deklaration von foo
vorzuziehen wäre, da es spezifischer ist (weniger Templates), obwohl es aussieht, dass mein Verständnis der Überladungsauflösung etwas fehlt. Interessanterweise ändert sich die zweite Deklaration, um X
wertmäßig zu nehmen, es "gut, gut" zu drucken und es X
durch nicht-konstante Referenz zu machen, lässt es "schlecht, gut" drucken. Das Entfernen der ersten Deklaration macht es offensichtlich "gut, gut", da es keine andere Wahl gibt.
Warum passiert das? Und vor allem, wenn der folgende Code nicht funktioniert, wie können Sie eine Funktion mit dieser Signatur überladen?
#include <iostream>
#include <string>
class X {};
template<typename T>
inline std::string foo(T && rhs) {
return "bad";
}
inline std::string foo(const X & rhs) {
return "good";
}
int main() {
std::cout << foo(X()) << std::endl;
X x;
std::cout << foo(x) << std::endl;
return 0;
}
Edit:
Vielleicht eine umständliche Lösung dieses Problem ist es indirekt zu tun. Befreien Sie sich von der ersten Form von foo
und verwenden Sie SFINAE, um zu überprüfen, ob eine gültige Überladung vorhanden ist. Sie ruft dann nicht foo_fallback
auf.
Ich habe mit einer Lösung für die Überlastung Teil kommen: http://mortoray.com/2013/06/03/overriding-the-broken-universal-reference-t/ –
1 + hour [youtube video] (https://www.youtube.com/watch?v=T5swP3dr190) zu diesem genauen Problem, das auf diese Frage auf unterhaltsame Weise zurückführt. – Yakk