2011-06-28 171 views
3

我花了幾個小時,當我意識到只有我的代碼的模板版本存在錯誤時才完全停留。模板代碼不工作,而非模板代碼工作!

在下面的代碼,當在myMap pushing_back元素,原始向量myVec1myVec2被修飾幷包含垃圾在執行結束。如果我取消所有模板的模板,只需用0123代替template<T>,那麼代碼就可以正常工作(原始數組不變)。

有趣的是,如果我將cout放在copy constructor中,如果代碼是模板化的,它不會被調用。但它會被調用,如果我用原始類型替換Vector<T2>的複製構造函數,然後一切工作正常。

爲什麼編譯器不知道T2==T因爲我只使用double

(請注意,代碼已儘可能縮短以顯示錯誤 - 因此刪除了訪問者,將所有內容公開化等)。

#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

模板構造函數永遠不會是複製構造函數。

所以你的類正在使用自動生成的拷貝構造函數。

乾杯&心連心,

+0

Ooohh!好,謝謝!!我會在3分鐘內接受答案 - 因爲stackoverflow不允許我以前接受它。謝謝! – WhitAngl

+1

引用標準(12.8/2,注4): 由於模板構造函數永遠不是複製構造函數,因此這種模板的存在並不會抑制複製構造函數的隱式聲明。模板構造函數與其他構造函數(包括複製構造函數)一起參與重載 解析,如果模板構造函數提供了比其他構造函數更好的匹配,則可以使用模板構造函數來複制該對象。 _italic_此鏈接可能會有所幫助_italic_ http://www.open-std.org/jtc1/sc22/open/n2356/special.html –