例如:
mat33 operator +(mat33& m1, mat33& m2);
mat33 operator -(mat33& m1, mat33& m2);
mat33 operator +(mat33&& m1, mat33&& m2);
mat33 operator -(mat33&& m1, mat33&& m2);
mat33 operator +(mat33&& m1, mat33& m2);
mat33 operator -(mat33&& m1, mat33& m2);
mat33 operator +(mat33& m1, mat33&& m2);
mat33 operator -(mat33& m1, mat33&& m2);
有无什么方法可以简化这一大串?
迷茫2017-04-17 15:40:40
如果你想要減少聲明的次數,那是有辦法的,簡化程式碼似乎不可能。依照你的聲明思路,&&,&&
和&&,&
可以將工作代理給&,&&
。這樣程式碼不複雜,也沒有重複。
這裡至少需要兩個實現,其中一個移動數據,另一個不移動數據。移動資料分lhs和rhs。同時也要兼顧ADL。實現這些至少需要聲明三個重載。用模板可以將聲明減少到兩個:
template <class T>
std::enable_if_t<std::is_convertible<T, mat33>::value, mat33>
operator+(T &&, const mat33 &) {
if (std::is_rvalue_reference<T &&>::value && !std::is_const<T>::value) {
std::cout << "move from lhs" << std::endl;
} else {
std::cout << "no move" << std::endl;
}
return {};
}
template <class T>
inline mat33 operator+(T &&lhs, mat33 &&rhs) {
std::cout << "rhs -> lhs, ";
return std::move(rhs)+lhs;
}
PS: c++17後可以用constexpr if實作靜態分枝。 c++17之前編譯器也通常可以完成這樣的最佳化。
測試程式碼:
#include <utility>
#include <type_traits>
#include <iostream>
namespace detail {
struct mat33 {};
template <class T>
std::enable_if_t<std::is_convertible<T, mat33>::value, mat33>
operator+(T &&, const mat33 &) {
if (std::is_rvalue_reference<T &&>::value && !std::is_const<T>::value) {
std::cout << "move from lhs" << std::endl;
} else {
std::cout << "no move" << std::endl;
}
}
template <class T>
inline mat33 operator+(T &&lhs, mat33 &&rhs) {
std::cout << "rhs -> lhs, ";
return std::move(rhs)+lhs;
}
} // namespace detail
int main() {
detail::mat33 a, b;
const detail::mat33 ca, cb;
// move from lhs
std::move(a)+b;
std::move(a)+cb;
// rhs -> lhs, move from lhs
a+std::move(b);
ca+std::move(b);
// no move
a+b;
ca+cb;
std::move(ca)+cb;
ca+std::move(cb);
a+cb;
ca+b;
std::move(ca) + b;
a + std::move(cb);
return 0;
}
高洛峰2017-04-17 15:40:40
mat33 operator +(const mat33& m1, const mat33& m2);
mat33 operator -(const mat33& m1, const mat33& m2);
不就搞定了。 。 。
const & 能符合所有引用(左值、右值、常數左值、常數右值)。