[英]Perfect forwarding with template classes
假設我有一個模板類,例如template<int n, int m> class Matrix
有沒有一種方法可以定義矩陣乘法運算符*
我的想法是
template< int n,int k, int m, template<int,int> class T1, template<int, int> class T2, template<int,int>class T3 >
T3<n,m> operator*(T1<n,k>&&, T2<k,m>&&)//does not work
當我嘗試運行以上代碼(以明顯的方式填充主體)時,出現錯誤:
無法從Matrix <1,1>轉換為Matrix <1,1> &&
當參數是左值時。
是。 從我自己的代碼:
template
<
int LeftColumnsRightRows, int LeftRows,
int RightColumns
>
Matrix<RightColumns, LeftRows> operator*(Matrix<LeftColumnsRightRows, LeftRows> const& a, Matrix<RightColumns, LeftColumnsRightRows> const& b)
而且我不知道您為什么要它接受&&
s。 如果要將其他兩個類型轉換為矩陣,然后將它們相乘,則應在乘法運算符之外進行轉換。
正如前面的答案所解釋的,我也將只堅持使用const引用。 但是要弄清楚為什么您的代碼不起作用,僅當您對cv-unqualified模板參數使用右值引用時,完美轉發才適用。 用外行的話來說,它必須只是T&&
,其中T
是函數模板參數:
template<class T>
void ForwardMe(T&& t)
{
DoSomething(std::forward<T>(t));
}
這個想法是,當傳遞一個左值時,編譯器將能夠推導T
為type&
(因此,由於引用折疊規則,函數簽名變為void ForwardMe(type&)
),或者在出現rvalue的情況下僅type
(簽名變為void ForwardMe(type&&)
)。
在您的示例中,您將執行以下操作:
template<int N, template<int> class T>
void ForwardMe(T<N>&& t)
{
// ...
}
這不符合您的預期,因為編譯器無法推斷T
為對某事物的引用,因此您無法獲得完美的轉發。 因此,函數參數t
將僅匹配右值引用。
由於const引用可以綁定到臨時對象,因此在上面的示例中使用const T<N>&
可以解決您的問題。 但是,如果您確實想同時支持左值和右值輸入(因為您希望在適當的位置具有移動語義),則有兩種選擇:
后者類似於:
#include <type_traits>
template<class L, class R>
struct MatrixMulResult_helper;
template<int n, int m, int k, template<int, int> class T>
struct MatrixMulResult_helper<T<n, m>, T<m, k>> { using type = T<n, k>; };
template<class L, class R>
using MatrixMulResult = typename MatrixMulResult_helper<L, R>::type;
template<class L, class R>
MatrixMulResult<std::decay_t<L>, std::decay_t<R>>
operator*(L&& lhs, R&& rhs)
{
// ...
}
編譯器現在可以自由推斷L
和R
作為參考。 MatrixMulResult<>
確保僅在L
和R
(的衰減類型)分別為T<n,m>
和T<m,k>
形式時定義此函數。 它返回一個T<n,k>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.