[英]Boost operators with mixed types - conversion and private members
我正在使用Boost-Operatators來構造矩陣類。 (玩具項目)。 但是,當我想要混合不同元素類型的矩陣時,我遇到了問題。
基本上我有一個模板類Matrix<T>
,其中T
是該矩陣的元素類型。 我正在使用Boost-Operators在Matrix<T>
實例之間定義運算符(例如,逐元素加法),在Matrix<T>
和T
之間定義運算符(例如標量乘法),如果可能,也在Matrix<T>
和Matrix<U>
之間定義運算符Matrix<U>
(例如實矩陣加復矩陣)。
boost運算符支持一個或兩個模板參數。 如果您想要兩個相同類型的對象之間的運算符,如果您想要混合運算符,則需要兩個運算符。
template<typename T>
class Matrix : boost::addable<Matrix<T>> // Add another matrix of same type.
boost::multiplyable2<Matrix<T>,T> // Scalar multiplication with a `T`.
但是,我不能將Matrix<U>
作為第二個參數,因為那時我的類將有兩個模板參數,類型將取決於我可以使用哪個矩陣。
template<typename T, typename U>
class Matrix : boost::addable2<Matrix<T,U>,Matrix<U,?>> // Now I have two template arguments.
// That's certainly not what I want!
我也試過實現我自己的boost::addable
版本,但這也不起作用。 編譯器抱怨不完整的類型。
template<class Derived>
class Addable {
template<class Other>
friend Derived operator+(Derived lhs, const Other &rhs) {
return lhs += rhs;
}
template<class Other>
friend Derived operator+(const Other &lhs, Derived rhs) {
return rhs += lhs;
}
};
另一種方法是從Matrix<U>
到Matrix<T>
定義一個強制轉換構造函數。 但是,現在我遇到了問題,那是兩種不同的類型,我無法訪問私有成員。 所以,我需要公開比我想要更多的東西,或者找到一種不同的方式來做到這一點。
你會如何實現這樣的事情?
#include <cassert>
#include <utility>
#include <complex>
#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/operators.hpp>
typedef double Real;
typedef std::complex<Real> Complex;
template<typename T>
class Matrix : boost::addable<Matrix<T>>
{
public:
Matrix() = default;
template<typename U>
Matrix(const Matrix<U> &other)
: m_(other.m()), n_(other.n()),
data_(other.data_.begin(), other.data_.end()) { }
Matrix(size_t m, size_t n) : m_(m), n_(n), data_(m*n) { }
Matrix(size_t m, size_t n, const T &initial)
: m_(m), n_(n), data_(m*n, initial) { }
size_t m() const { return m_; }
size_t n() const { return n_; }
size_t size() const {
assert(m_*n_ == data_.size());
return data_.size();
}
const T &operator()(size_t i, size_t j) const { return data_[i*m_ + j]; }
T &operator()(size_t i, size_t j) { return data_[i*m_ + j]; }
void fill(const T &value) {
std::fill(data_.begin(), data_.end(), value);
}
Matrix &operator+=(const Matrix &other) {
assert(dim_match(other));
for (int i = 0; i < size(); ++i) {
data_[i] += other.data_[i];
}
return *this;
}
friend std::ostream &operator<<(std::ostream &o, const Matrix &m) {
if (m.size() == 0) {
o << "()" << std::endl;
return o;
}
for (int i = 0; i < m.m(); ++i) {
o << "( ";
for (int j = 0; j < m.n() - 1; ++j) {
o << m(i,j) << ", ";
}
o << m(i, m.n() - 1) << " )" << std::endl;
}
return o;
}
private:
bool dim_match(const Matrix &other) {
return n_ == other.n_ && m_ == other.m_;
}
private:
int m_, n_;
typedef std::vector<T> Store;
Store data_;
};
int main() {
Matrix<Real> A(2,3, 1.);
Matrix<Complex> B(2,3, Complex(0,1));
auto C = Matrix<Complex>(A) + B;
std::cout << A << std::endl;
std::cout << B << std::endl;
std::cout << C << std::endl;
}
我就是這樣做的:使用朋友模板函數(參見運算符重載 :成員與非成員之間的決策):
template<typename T>
class Matrix
{
public:
template<typename> friend class Matrix;
然后是
template <typename T1, typename T2>
Matrix<typename std::common_type<T1, T2>::type>
operator+(Matrix<T1> const& a, Matrix<T2> const& b)
{
Matrix<typename std::common_type<T1, T2>::type> result(a);
return (result += b);
}
請注意使用common_type
來獲得合理的結果類型(您可能希望在那里引入自己的特性以滿足您的特定要求)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.