Dies ist nur, wie die Überladungsauflösung funktioniert. Wenn die Suche abgeschlossen ist, werden sowohl die Vorlage als auch die Funktion gefunden. Die Vorlagentypen werden dann abgeleitet und die Überladungsauflösung beginnt. Im Fall eines Arguments des Typs MyClass
die beiden candiates sind:
void func<MyClass>(MyClass const&);
void func(MyClass const&);
die gleichermaßen gute Spiele für die Argumente sind, aber der zweite ist ein Nicht-Template sind bevorzugt. Im Fall von MyClassDer
:
void func<MyClassDer>(MyClassDer const&);
void func(MyClass const&);
In diesem Fall ist die erste ein besserer Kandidat ist als die zweite, als die zweite erfordert eine abgeleitetes-Basis-Umwandlung und das aufgenommen wird.
Es gibt verschiedene Ansätze zum direkten Versand, um Ihren Code zu treffen. Die einfachste ist nur die Art des Arguments Nötigung sein MyClass
und Rückfall so auf den ursprünglichen Fall: einfache
func(static_cast<MyClass&>(myClassDer));
Während dies muss überall getan werden, und wenn Sie nur an einer Stelle vergessen, die falsche Sache wird heißen. Der Rest der Lösungen sind Komplex und Sie könnten prüfen, ob es nicht besser wäre, nur verschiedene Funktionsnamen bereitzustellen.
Eine der Optionen ist SFINAE mit der Vorlage zu deaktivieren, wenn der Typ von MyClass
abgeleitet:
template <typename T>
typename std::enable_if<!std::is_base_of<MyClass,MyClassDer>::value>::type
func(T const & t) { ... }
In diesem Fall wird nach Nachschlag wird der Compiler-Typ Abzug durchführen, und es wird ableiten T
zu be , wird es dann den Rückgabetyp der Funktion auswerten (SFINAE könnte auch auf ein anderes Vorlage- oder Funktionsargument angewendet werden). Die is_base_of
ergibt false
und die enable_if
wird keinen verschachtelten Typ haben. Die Funktionsdeklaration wird schlecht gebildet und der Compiler wird sie fallen lassen, wobei die Auflösung mit einem einzelnen Kandidaten, der Nicht-Template-Überladung, gesetzt bleibt.
Eine weitere Option wäre die Bereitstellung einer einzelnen Vorlagenschnittstelle und die interne Verteilung an eine Vorlage oder die Überladung (mit einem anderen Namen) mittels Tag-Versand. Die Idee ist ähnlich, Sie bewerten das Merkmal innerhalb der Vorlage und rufen eine Funktion mit einem Typ auf, der aus dieser Auswertung generiert wurde.
template <typename T>
void func_impl(T const&, std::false_type) {...}
void func_impl(MyClass const&, std::true_type) {...}
template <typename T>
void func(T const &x) {
func_impl(x,std::is_base_of<MyClass,MyClassDer>::type());
}
Es gibt andere Alternativen, aber das sind zwei gewöhnlichsten und der Rest auf den gleichen Prinzipien basieren hauptsächlich.
Betrachten Sie erneut, ob das Problem die Komplexität der Lösung wert ist. Sofern der Aufruf an func
nicht innerhalb des generischen Codes erfolgt, löst eine einfache Änderung des Funktionsnamens das Problem, ohne unnötigerweise Komplexität hinzuzufügen, die Sie oder die anderen Betreuer möglicherweise nicht pflegen können.
Dies scheint die richtige Lösung zu sein. Ich werde sehen, wie ich das mit Boost umsetzen kann. – user2811040
@ user2811040 'boost :: enable_if' und' boost :: is_base_of'. Das ist es. – Angew
@ user2811040 Und ohne C++ 11, verschieben Sie den zweiten Template-Parameter auch auf den Zeiger-Trick. – Angew