spaß mit vererbung
-
Fehlermeldung
error C2784: 'bool operator <(const ccomparable<t> &,const t &)' : could not deduce template argument for 'const ccomparable<t> &' from 'const cmonomial<tresult,targument>' with [ tresult=float, targument=float ] d:\programmierung\vc++ 2005 express edition\bin\base classes\comparable.h(25) : see declaration of 'operator <'dazu folgender C++ Codeausschnitt
template<class t> class ccomparable { public: virtual int compare(t const &src) const = 0; //... }; template<class t> bool operator < (ccomparable<t> const &lhs, t const &rhs) { return lhs.compare(rhs) < 0; }; template<class tresult, class targument> class cmonomial : virtual public ccomparable<cmonomial<tresult, targument>> { public: int compare(cmonomial<tresult, targument> const &src) const; //... }; int main() { cmonomial<float, float> m1, m2; bool less = false; less = (m1 < m2); // hier kommt die opbige fehlermeldung return 0; };ich versteh halt nicht wo das problem ist, aber vllt hab ich da was mit der vererbung nicht richtig verstanden.
danke schon mal im voraus für ratschläge zum lösen des problems.
-
const ccomparable<t> & ist ein deduzierbarer Kontext, dass heißt, für ein gegebenes Argument, kann der Templateparameter t aus diesem Argument prinzipiell bestimmt werden.
in m1 < m2 ist der linke Operand vom Typ cmonomial<float, float>, das ist keine Instanz des Templates ccomparable, mithin kann für dieses Funktionsargument der Templateparameter T nicht deduziert, und damit der tatsächliche Funktionsparameter substituiert werden. Das ist also ein Fall für SFINAE - streng genommen besteht der Fehler nicht darin, dass das Templateargument nicht ermittelt werden kann, sondern darin, dass keine geeignete Überladung übrigbleibt - das wäre aber wohl nicht so hilfreich für den Programmier.Was du zu beabsichtigen scheinst ist etwas anderes: das linke Argument soll nur in ein geeignetes ccomparable<t> konvertierbar sein - dass bedeutet, dass für dieses Argument keine Templateparameterdeduktion stattfinden darf (denn dies unterdrück alle Konvertierungen für dieses Argument außer ggf. Qualifikationskonvertierung). Der Trick muss daher darin bestehen, den Typ zwar als ccomparable<t> zu bestimmen, aber diesen in einen nicht deduzierbaren Kontext zu setzen: klassisch ist TT<T>::X so ein Fall:
template<typename T> struct identity { typedef T type; }; // Hilfstemplate template<class t> bool operator < (typename identity<ccomparable<t> >::type const &lhs, t const &rhs) { return lhs.compare(rhs) < 0; };
-
also so ganz versteh ich das nicht, meine cmonomial-klasse ist doch von ccomparable abgeleitet und müsste doch dann auch auf diesem operator anspringen.
mal abgesehen davon gibts vllt noch ein weiteres problem mit der externen deklaration des operators <.
class A :virtual public ccomparable<int> { //... }; class B :virtual public ccomparable<int> { //... };dann hätte ich doch rein theoretisch zweimal
bool operator < (ccomparable<int> const &lhs, int const &rhs);deklariert oder der compiler weiß dann nicht welchen er nehmen soll, obwohl das eigentlich klar ist, jenachdem welcher typ auf ccomparable reduziert wird.