2011-09-26 46 views
1

所以我剛剛瞭解到(謝謝你們)decltype。我現在可以寫非常好的載體模板,實際上跑贏valarrays(!):C++更廣義的操作員模板

template <typename T, typename U> 
vector<decltype(T()*U())> operator*(const vector<T>& A, const vector<U>& B){ 
    vector<decltype(T()*U())> C = vector<decltype(T()*U())>(A.size()); 
    typename vector<T>::const_iterator a = A.begin(); 
    typename vector<U>::const_iterator b = B.begin(); 
    typename vector<decltype(T()*U())>::iterator c = C.begin(); 
    while (a!=A.end()){ 
    *c = (*a) + (*b); 
    a++; b++; c++; 
    } 
    return C; 
} 

是否有可能使這種模板更是「元」的,在這個意義上,我們允許操作員(「*」 )本身是一個模板參數?即有一個適用於*,+,%等的模板定義,其中適當的操作符op用於* c =(* a)op(* b)?

我打賭它不是,但它會很好!

+0

這是本質accumulate'的'二進制版本,雖然'accumulate'本身已經可以用於類似的東西,雖然不完全對稱。不過,真正的力量可能來自懶惰評估包裝。 –

+0

...幾個nitpicks:你可能想要使用'C'和'reserve'的默認構造來確保它不需要增長,然後使用'push_back'(而不是用大小 - 創建大小的數組與'vector c = vector (a.size())' - 並重寫元素)。使用typedefs!它們有助於可讀性,單個'typedef decltype(A.front()* B.front())result_type'將使代碼更具可讀性。避免向泛型代碼中添加不需要的要求(當前實現使用'T()','U()'和'result_type()'強加一個默認構造函數) –

+0

@DavidRodríguez-dribeas:我發現使用push_back比完整的申報/重寫版本慢得多,在我的測試案例中速度降低了50%。 – andyInCambridge

回答

2

如您所料,此答案爲「否」。 :)

但是,您可以使用預處理產生這樣的功能:

#define OPERATOR_BLOB(optype) \ 
    vector<…> operator optype (…) { … } 

OPERATOR_BLOB(*) 
OPERATOR_BLOB(+) 
… 
+0

謝謝!這似乎是正確的路要走。 – andyInCambridge

0

使用std::declval<T&&>(),而不是僅僅T(),它可能不會有一個默認的構造函數(因爲的std ::矢量不需要默認構造函數,只有一個拷貝構造函數)。 非常確定關於&類型參考&右值引用的正確性和轉發,對於值,引用,常量引用,右值引用,類可以實現不同的事情。用幾個類來測試它。

另外,請注意,由於未實現的功能,返回類型提取可能不適用於GCC中的複合賦值運算符。

是的,我在我的指針包裝類參數宏解決它:http://frigocoder.dyndns.org/code/Frigo/Lang/ref

例如

#define PROXY_BINARY_OPERATOR(_) \ 
    template <class Arg> \ 
    decltype(std::declval<T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) \ 
    { \ 
     return std::forward<T>(get()) _ std::forward<Arg>(arg); \ 
    } \ 
    template <class Arg> \ 
    decltype(std::declval<const T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) const \ 
    { \ 
     return std::forward<T>(get()) _ std::forward<Arg>(arg); \ 
    }