Frage

Angesichts der folgenden Funktionsvorlagen:

#include <vector>
#include <utility>

struct Base { };
struct Derived : Base { };

// #1
template <typename T1, typename T2>
void f(const T1& a, const T2& b)
{
};

// #2
template <typename T1, typename T2>
void f(const std::vector<std::pair<T1, T2> >& v, Base* p)
{
};

Warum ruft der folgende Code immer Überladung #1 anstelle von Überladung #2 auf?

int main()
{
    std::vector<std::pair<int, int> > v;
    Derived derived;

    f(100, 200);  // clearly calls overload #1
    f(v, &derived);         // always calls overload #1

    return 0;
}

Vorausgesetzt, der zweite Parameter von f ist eine abgeleitete Art von Base, Ich hatte gehofft, dass der Compiler Überladung #2 auswählt, da er besser übereinstimmt als der generische Typ in Überladung Nr. 1.

Gibt es Techniken, mit denen ich diese Funktionen umschreiben könnte, damit der Benutzer Code wie in der angezeigt werden kann main Funktion (z.

War es hilfreich?

Lösung

Sie können das entweder tun:

f(v, static_cast<Base*>(&derived));

Oder verwenden Sie Sfinae, um die erste Funktion als Auswahlkandidat zu entfernen:

// Install boost library and add these headers:
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>

// #1 - change it to look like this (note the keyword void changed positions)
template <typename T1, typename T2>
typename boost::disable_if<
   typename boost::is_convertible<T2, Base*>, void>::type
f(const T1& a, const T2& b)
{
};

// #2 - this one can stay the same
template <typename T1, typename T2>
void f(const std::vector<std::pair<T1, T2> >& v, Base* p)
{
};

Andere Tipps

Da der zweite Parameter von F ein abgeleiteter Basistyp ist

Es ist mit solchen umwandelbar, aber es ist ein abgeleiteter*. Die erste Vorlagenfunktion erfordert keine Konvertierungen, die zweite erfordert eine, daher wählt sie die erste aus.

Dies wählt die zweite:

f(v, static_cast<Base*>(&derived));

Als Randnotiz, main Gibt ein zurück int.

Neben den offensichtlichen Themen um Koenig Lookup Das ist von Compilern mehr oder weniger gut implementiert (insbesondere ältere sind ziemlich problematisch), es gibt einige Fallstricke in Bezug auf Vorlagespezialisierung.

Die Spezialisierung erfordert, dass die Typen genau übereinstimmen (nicht sicher, wie die STD dies definiert, aber aus meiner Erfahrung [GCC, MSVC] wird eine abgeleitete Klasse nicht übereinstimmen). Wenn Sie eine hässliche Besetzung zu Base*hinzufügen, sollte sie wie Sie beabsichtigt funktionieren, fügen Sie optional eine weitere Spezialisierung für abgeleitete ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top