Domanda

Data la seguente funzione di modelli:

#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)
{
};

Perché è che il codice riportato di seguito sempre richiama sovraccarico #1 invece di sovraccarico #2?

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;
}

Dato che il secondo parametro di f è un tipo derivato di Base, Speravo che il compilatore avrebbe scelto di sovraccarico #2 in quanto è una migliore corrispondenza di tipo generico in sovraccarico #1.

Ci sono tecniche che ho potuto utilizzare per la riscrittura di queste funzioni, in modo che l'utente può scrivere il codice visualizzato nell' main funzione (cioè, sfruttando il compilatore detrazione di tipi di argomento)?

È stato utile?

Soluzione

È possibile fare questo:

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

In alternativa, utilizzare SFINAE per rimuovere la prima funzione come candidato selezione:

// 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)
{
};

Altri suggerimenti

  

Dato che il secondo parametro di f è un tipo derivato di Base

E 'convertibile in tale, ma è un Derivato *. La prima funzione modello richiede nessuna conversione, e il secondo necessita di uno, quindi sceglie il primo.

Questo sceglie la seconda:

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

Una nota a parte, main restituisce una int.

Oltre all'evidente argomenti su Ricerca Koenig che è più o meno ben implementata dai compilatori (soprattutto quelli più vecchi sono abbastanza problematico), ci sono un paio di insidie per quanto riguarda modello di specializzazione.

La specializzazione richiede i tipi di corrispondere esattamente (non sono sicuro di come la std definisce tale, ma dalla mia esperienza [gcc, msvc] una classe derivata non essere abbinati).Se si aggiunge un brutto cast di Base*, dovrebbe funzionare come previsto, in alternativa, aggiungere un altro specializzazione per le Derivate...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top