2010-12-04 11 views
4

Hier ist ein paar verwandte, aber unterschiedliche Klassen. Einer enthält eine Liste von Schwimmern; man enthält nur einen. Manchmal möchte ich, sagen wir, diese zusammen vermehren. In diesem Fall möchte ich die Nicht-Liste zu einer Liste "befördern". Hier ist der Code, der genau so funktioniert, wie ich es möchte.Implizite Konvertierung passiert nicht, wenn ich templatize

#define LIST_SZ 4 

class Vec1; 

class Vec1_list { 

    public: 
     Vec1_list() {} 
     Vec1_list(const Vec1& in); 

     float x[LIST_SZ]; 
}; 

class Vec1 { 

    public: 
     Vec1() {} 
     Vec1(const float& in); 

     float x; 
}; 

Vec1::Vec1(const float& in) { 
    x = in; 
} 

Vec1_list::Vec1_list(const Vec1& in) { 
    for (int i = 0; i < LIST_SZ; i++) { 
     x[i] = in.x; 
    } 
} 

Vec1_list operator*(const Vec1_list& a, const Vec1_list& b) { 
    Vec1_list tmp; 

    for (int i = 0; i < LIST_SZ; i++) { 
     tmp.x[i] = a.x[i]*b.x[i]; 
    } 

    return tmp; 
} 

int main(void) { 
    Vec1 v1; 
    Vec1_list v2, v3, answer; 

    answer = v1*v3; 
} 

Aber jetzt sage ich es wie so templatize wollen ....

#define LIST_SZ 4 

template <typename T> class Vec1; 

template <typename T> 
class Vec1_list { 

    public: 
     Vec1_list() {} 
     Vec1_list(const Vec1<T>& in); 

     T x[LIST_SZ]; 
}; 

template <typename T> 
class Vec1 { 

    public: 
     Vec1() {} 
     Vec1(const T& in); 

     T x; 
}; 

template <typename T> 
Vec1<T>::Vec1(const T& in) { 
    x = in; 
} 

template <typename T> 
Vec1_list<T>::Vec1_list(const Vec1<T>& in) { 
    for (int i = 0; i < LIST_SZ; i++) { 
     x[i] = in.x; 
    } 
} 

template <typename T> 
Vec1_list<T> operator*(const Vec1_list<T>& a, const Vec1_list<T>& b) { 
    Vec1_list<T> tmp; 

    for (int i = 0; i < LIST_SZ; i++) { 
     tmp.x[i] = a.x[i]*b.x[i]; 
    } 

    return tmp; 
} 

int main(void) { 
    Vec1<float> v1; 
    Vec1_list<float> v2, v3, answer; 

    answer = v1*v3; 
} 

Die 'mult' bewirkt, dass der Compiler diese Zeit ersticken - es wird nicht automatisch meine Vec1 aufrufen -> Vec1_list Konstrukteur. Ist das eine Tatsache des Lebens in C++, oder gibt es eine Methode, die ich verwenden kann, um dies automatisch zu erreichen? Die Alternative ist, dass ich einen riesigen Fan von Funktionen haben muss.

Antwort

1

Sie müssen die operator* als Freund der Vec1_list Klasse deklarieren, so dass es instanziiert wird, wenn die Vec1_list instanziiert wird und dann die Konvertierung durchgeführt wird.

EDIT: Dazu der Bediener * Definition der Vec1_list Klasse Template-Deklaration verschieben:

friend static Vec1_list operator*(const Vec1_list& a, const Vec1_list& b){ 
    /* ... */ 
} 
0

Ich weiß nicht, warum es nicht zum gewünschten Vec1_list fördert. Aber wenn es nicht möglich ist, dann kann man dies immer tun:

template <typename T> 
Vec1_list<T> operator*(const Vec1<T>& a, const Vec1_list<T>& b) { 

    return Vec1_list<T>(a)*b;; 
} 

By the way, ich bin zu graben immer noch das ursprüngliche Problem.

1

Ihre benutzerdefinierte Konvertierung durch einen Konvertierungskonstruktor wird von der Vorlagendifferenz nicht berücksichtigt.

Der Vorlagenabzug versucht, eine Ersetzung der Funktionsschablonenparameter zu finden, die den parametrisierten Typ zu den Argumenttypen identisch machen. Wenn es nicht möglich ist, ist es erlaubt (ich vereinfache es hier): const/volatile Qualifikationsmodifikationen oder 'abgeleitet zu Base' Zeigerkonvertierung.

Dies wird in Abschnitt 14.8.2.1/3 des Standards [temp.deduct.call] beschrieben.

Verwandte Themen