2011-06-28 6 views
3

私のコードのテンプレート版だけがバグを持っていることに気づいたとき、私は数時間を過ごしました。テンプレート化されていないコードが動作している間、テンプレート化されたコードは動作しません!

myMapのpushing_back要素を使用すると、元のベクトルmyVec1myVec2は変更され、実行の最後にガベージが含まれます。私はすべてのテンプレートを解除する場合は、ちょうどtemplate<T>を二重に置き換えると、コードは正常に動作します(元の配列はそのままです)。

coutcopy constructorに入れれば、コードがテンプレート化されていると呼び出されないというのは面白いことです。しかし、コピーコンストラクタをVector<T2>で元のタイプのVector<T>で置き換えると、それが呼び出されます。すべて正常に動作します。

私はdoubleしか使用していないので、なぜコンパイラはT2==Tを知らないのですか?

(注:できるだけコードを短くしてエラーを表示していますので、アクセサーを削除してすべてを公開しましたなど)。

#include <vector> 
#include <map> 


template<class T> 
class Vector{ 
public: 
    Vector():n(0),data(0){}; 
    Vector(int N):n(N),data(new T[N]){}; 
    Vector(T x, T y):n(2),data(new T[2]){data[0]=x; data[1]=y;}; 
    template<class T2> Vector(const Vector<T2>& rhs):n(rhs.n), data(new T[n]) 
    { 
     for (int i=0; i<n; i++) 
      data[i] = T(rhs.data[i]); 
    } 
    ~Vector(){delete[] data;} 

    Vector& operator=(const Vector& rhs) 
    { 
     if (rhs.n != n) 
     { 
      if (data) 
       delete[] data; 
      data = new T[rhs.n]; 
     } 
     n = rhs.n; 
     memcpy(data, rhs.data, n*sizeof(T)); 
     return *this; 
    } 
    T& operator[](int i){return data[i];} 
    const T& operator[](int i) const {return data[i];} 
    int n; 
    T* data; 
}; 

typedef Vector<double> Vectord; 

template <class T> inline bool operator<(const Vector<T>& v1, const Vector<T>& v2) 
{ 
    for (int i=0; i<v1.n; i++) 
    { 
     if (v1[i]<v2[i]) return true; 
     if (v1[i]>v2[i]) return false; 
    } 
    return false; 
} 


int main(int argc, char** argv) 
{ 
    std::vector<Vectord> myVec1(3); 
    myVec1[0] = Vectord(1.,3.); 
    myVec1[1] = Vectord(3.,3.); 
    myVec1[2] = Vectord(1.,5.); 

    std::vector<Vectord> myVec2(3); 
    myVec2[0] = Vectord(4.,1.); 
    myVec2[1] = Vectord(2.,5.); 
    myVec2[2] = Vectord(6.,5.); 

    std::map<Vectord, std::vector<Vectord> > myMap; 
    for (int i=0; i<3; i++) 
    { 
     myMap[myVec1[i]].push_back(myVec2[i]); 
    } 



    return 0; 
} 
+0

は、あなたはそれを上に考えなければならない<'、この順序は、これにより少なくとも驚きの原則を傷つけ、実際のベクトル特性を表すものではありませんので。むしろ、それを 'strictweakordering'関数として宣言して、これを' map'に与えることをお勧めします。 (たとえ実装が、たとえstlのものであっても、この原則を傷つける例がたくさんありますが) – leftaroundabout

答えて

9

テンプレートコンストラクタは決してコピーコンストラクタではありません。

あなたのクラスは自動的に生成されたコピーコンストラクタを使用しています。それは本当に `演算子をオーバーロードすることをお勧めします場合

乾杯& HTH。、

+0

Ooohh!ありがとうございました!私は3分で答えを受け入れるでしょう - stackoverflowはそれを前に受け入れることができません。ありがとう! – WhitAngl

+1

標準からの引用(12.8/2、注4): テンプレートコンストラクタは決してコピーコンストラクタではないので、そのようなテンプレートが存在しても、コピーコンストラクタの暗黙の宣言は抑制されません。テンプレートコンストラクタは、コピーコンストラクタを含む他のコンストラクタとオーバーロード の分解能に参加し、テンプレートコンストラクタを使用して、他のコンストラクタよりも優れた一致を提供するオブジェクトをコピーできます。 _italic_このリンクは役に立ちます_italic_ http://www.open-std.org/jtc1/sc22/open/n2356/special.html –

関連する問題