簡體   English   中英

提升混合類型的運算符 - 轉換和私有成員

[英]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來獲得合理的結果類型(您可能希望在那里引入自己的特性以滿足您的特定要求)

看到Live On Coliru

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM