Da Sie keine expliziten Template-Argumente zu find
(wie in find<float>(myFloat, 9.83)
) vorsah, muss der Compiler das Template-Argument T
aus den Funktionsargumenten abzuleiten.
Während der Templatargumentableitung wird jedes Erscheinungsbild eines Template-Parameters in den Funktionsparametertypen entweder in einem abgeleiteten Kontext oder einem nicht-abgeleiteten Kontext angezeigt. In Ihrem Fall werden beide als abgeleiteter Kontext betrachtet. Ein Typ oder Wert wird für jede Darstellung eines Vorlagenparameters in einem abgeleiteten Kontext bestimmt.
myFloat
std::shared_ptr<Node<float>>
hat und der erste Funktionsparameter eingeben hat std::shared_ptr<Node<T>>
Typen, so wie T
float
abgeleitet wird.
9.83
hat double
-Typ und der zweite Funktionsparameter hat T
eingeben, so T
als Doppel abgeleitet wird.
Da der Vorlagenparameter T
zu zwei verschiedenen Typen abgeleitet wurde, schlägt der Gesamtabzug fehl! Wenn der gleiche Template-Parameter mehr als einmal abgeleitet wird, müssen alle Ergebnisse identisch sein.
Was können Sie tun, damit dies funktioniert?
Eine unangenehme Lösung wäre, die Vorlage in Ruhe zu lassen und die Anrufer zu bitten, sie vorsichtig zu verwenden. find<float>(myFloat, 9.83)
würde funktionieren, indem das Template-Argument explizit bereitgestellt wird. find(myFloat, 9.83f)
würde funktionieren, indem Sie den Typ des zweiten Funktionsarguments ändern. Aber es ist besser, die Vorlage flexibler und freundlicher zu gestalten.
Eine einfache Lösung besteht darin, einfach zwei verschiedene Vorlagenparameter zu verwenden.
template<class T, class U>
int find(std::shared_ptr<Node<T>> ptr, U val);
Dann erfordert die Funktion einfach, dass der ==
Operator für die Typen arbeitet T
und U
.
Oder wenn Sie die zweite Funktion Argument wollen implizit auf den in den Node
verwendeten Typ umgewandelt wird, könnten Sie absichtlich die zweite Verwendung von T
in einen nicht abgeleiteten Kontext drehen:
template <typename T>
struct identity {
using type = T;
};
template<class T>
int find(std::shared_ptr<Node<T>> ptr,
typename identity<T>::type val);
von Erschienenen links von ::
ist der zweite T
jetzt ein nicht-abgeleiteter Kontext, daher wird der Ausdruck find(myFloat, 9.83)
nur vom ersten Argument T
ableiten, was zu T=float
führt, dann in die Template-Funktionsdeklaration ersetzen. typename identity<float>::type
funktioniert bis float
, so wird es eine implizite Umwandlung von double
Literal 9.83
zu float
geben, um die Funktion aufzurufen.
Wie ist 'myFloat' definiert? – DimChtz
Aktualisiert mit '' myFloat'' Definition – kmiklas
[OT]: Da 'find' nicht Besitz übernimmt, besser durch Referenz/Zeiger anstelle von Smart Pointer – Jarod42