2014-04-18 49 views
0

我需要動態創建包含不同數值類型的數組,包括char,int,unsigned int,float,double。我想能夠創建任何兩個這些陣列,並假設它們具有相同的長度,實現算術運算符,如運算符+ =添加不同類型的數組(C++)

我已經能夠實現該數組作爲模板,但我不知道如何實現任何算術運算符,因爲我不知道在編譯時其他數組的類型是什麼,或者甚至當第一個數組被創建時(我將知道我構建的數組的類型)。我看着std :: array,但它不支持算術運算符。另一種選擇,這是絕對不優雅(但不工作),是實施一系列類型的特定運營商,如

MyArray<V> operator+ (const MyArray<float>& addend) const; 
MyArray<V> operator+ (const MyArray<double>& addend) const; 
MyArray<V> operator+ (const MyArray<int32>& addend) const; 
MyArray<V> operator+ (const MyArray<int16>& addend) const; 

感謝您的任何意見。

+1

這些操作員需要做什麼?如果它們是簡單的算術,那麼你爲什麼必須自己寫它們? – ZivS

+1

這可能是一個實例,運算符重載不是一個好的選擇,恕我直言。 'std :: transform(this-> begin(),this-> end(),addend.end(),output-> begin(),std :: plus ());' – IdeaHat

+0

爲了擴展,二元運算符重載只有當你能保證他們有意義時纔有意義。這看起來很簡單,但你需要保證像'a + b == b + a'這樣的東西,你的情況顯然不會(返回類型不一致)。另外,看起來你正在爲每個運算符分配一個新的數組,這將產生不必要的開銷。 – IdeaHat

回答

0

您可以使用一個多模板參數:

template<class V, class T> MyArray<V> operator+ (const MyArray<T>& addend) const; 

然後投將始終按照你的主數組類型。

+0

不,它被轉換爲任意的第一個參數。假設A是'MyArray ',而B是'MyArray '。 A + B將會返回一個'MyArray '(底層的數學計算方式爲「float」,然後轉換爲「int」)。 'B + A'將返回'MyArray '。 'A [0] + B [0]'將返回一個'float','B [0] + A [0]'將返回一個'float'。您應該使用C++的升級規則,或者不要使用模板參數無法明確設置的運算符。 – IdeaHat

0

您可能需要根據某些類型特徵選擇的結果類型來調度您的操作。

簡化了許多(無載體):

#include <iostream> 

template <typename T> 
struct Number { 
    T value; 
    Number(T value) : value(value) {} 

    template <typename U> 
    explicit Number(U value) : value(value) {} 

    operator T() const { return value; } 
}; 

#define C_PLUS_PLUS_11 (201103L <= __cplusplus) 

template <typename U, typename V> 
struct binary_operation_traits { 
    #if C_PLUS_PLUS_11 
    typedef decltype(U() + V()) result_type; 
    #endif 
}; 

#if ! C_PLUS_PLUS_11 
template <typename T> 
struct binary_operation_traits<T, T> { 
    typedef T result_type; 
}; 

template <> 
struct binary_operation_traits<int, float> { 
    typedef float result_type; 
}; 

template <> 
struct binary_operation_traits<int, double> { 
    typedef double result_type; 
}; 

// And so on ... 

#endif 

template <typename U, typename V> 
Number<typename binary_operation_traits<U, V>::result_type> 
operator + (const Number<U>& a, const Number<V>& b) { 
    typedef typename binary_operation_traits<U, V>::result_type result_type; 
    return Number<result_type>(result_type(a) + result_type(b)); 
} 

int main() 
{ 
    Number<int> a(1); 
    Number<double> b(1.5); 
    std::cout << a + b << '\n'; 
    return 0; 
} 
1

好吧,它可能是從我在這個線程,這是一個特別的痛處,我一切的評論明顯不夠。這是有原因的,我曾經像你一樣。我喜歡,我可以重載操作員!驚人!過載所有操作員(這是與一個自定義圖像容器類型)。過了一段時間,一些事情變得清晰:

  1. 運營商很難正確申報,尤其是模板化的申報者。
  2. 模板運算符不能明確地設置它們的類型,只能隱式地設置。
  3. 操作順序一直沒有意義。
  4. 運算符必須使用異常作爲它們在所有情況下都不理想的「失敗」模式,或者如果可以在編譯時檢測到失敗,則使用「enable-if」類型語法。
  5. 運算符意義很難記錄/闡明。對運營商應該「做什麼」的不同解釋使得很難弄清楚。 (MyArray<T>+MyArray<J>是否應該像T+J那樣工作,或者應該像'串+字符串'一樣工作?)
  6. 運算符必須按值返回,如果您的移動沒有​​正確設置,則會導致開銷/你不在C++ 11 /出於任何原因返回值elision不會發生。
  7. 總的來說,編寫自己的容器類型是重做STL已經完成的大量工作的好方法。

,你可以不喜歡它(在命名空間範圍)(假設你有一個模板轉換運算符)

template <typename T, typename J> 
MyArray<decltype(T()+J())> operator+(const MyArray<T>& x,const MyArray<J>& y) 
{ 
    using K=decltype(T()+J()); 
    MyArray<K> ret(x.size());//or something? 
    for (size_t i = 0; i < x.size(); i++) {ret[i]=x[i]+y[i];}//could replace with foreach 
    return ret; 
}; 

雖然使用與載體以下只是更有意義。如果需要,您可以將其封裝在「添加」電話中。

std::vector<T> a;//or whatever 
std::vector<J> b;//or whatever 
std::vector<K> c(a.size());//note: you can still use the decl type here, OR just define it to whatever you actually want it to be 
std::transform(a.begin(), a.end(). b.begin(), c.begin(), std::plus<K>()); 

如果你正在嘗試做這一切的地方,並試圖使矩陣數學庫,使用一個像徵,它會爲您節省了大量的工作,這將是強類型作爲一個矩陣,而不是一個通用的集合,它將完成與Eigen團隊的全部數學知識。