Domanda

Se ho una classe base modello con un metodo modello:

template <typename T>
class S
{
public:

    template <typename U>
    void f(U p, typename enable_if<is_same<T, U> >::type*dummy = 0)
    {
        std::cout << p << std::endl;
    }
};

Per l'esempio, semplifico il metodo: deve "esiste" solo se t == u

Se A è questa classe:

class A : public S<int> {};

Allora ho quello che voglio:

int i = 1;
A a;
a.f(i);

compila, ma

double d = 2.0;
a.f(d);

Non compila: Errore: nessuna funzione di corrispondenza per la chiamata a 'A :: F (Double &)' È il comportamento atteso.

Ora facciamo eredità da S<double> anche :

class A : public S<int>, public S<double> {};

Quindi il seguente codice non si compila:

int i = 1;
A a;
a.f(i);
error: request for member ‘f’ is ambiguous

error: candidates are: template<class U> void S::f(U, typename
boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T =
double]

error:                 template<class U> void S::f(U, typename
boost::enable_if<boost::is_same<T, U>, void>::type*) [with U = U, T =
int]

Mi aspettavo che non ci fosse ambiguità: f<int> esiste solo per S<int>

Nell'errore del compilatore, possiamo notare che T è noto quando questo pezzo di codice è compilato, ma non u (u = u).

Qualche spiegazione o "soluzione alternativa"?

È stato utile?

Soluzione

Prova questo:

a.S<int>::f(i);

... o alternativamente iniettare la funzione in A, per esempio

class A : public S<int>, public S<double> 
{
public:
  using S<int>::f;
  using S<double>::f;
};

Altri suggerimenti

Hai ragione esiste solo in S, ma due volte. Una volta per ogni tipo, int e doppio. Quindi, nel tuo caso, dovrai specificare esattamente quale funzione vuoi chiamare. La soluzione di NIM funziona proprio così.

Others have given good workarounds, but I want to answer that other question you had

I expected there is no ambiguity : f<int> exists only for S<int>.

You said a.f(i) so it first needs to look for name f in A. It finds two fs. In S<int> and S<double>. At name lookup time, it does not know yet that it later could have only selected S<int>::f as a winner because S<double>::f would be thrown away by SFINAE. The clear separation of name lookup and overload resolution and template argument deduction does not allow such intermingling.

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