gpt4 book ai didi

c++ - 具有混合类型的 Boost 运算符 - 转换和私有(private)成员

转载 作者:太空狗 更新时间:2023-10-29 21:43:53 26 4
gpt4 key购买 nike

我正在使用 Boost-Operatators构造一个矩阵类。 (一个玩具项目)。但是,当我想混合不同元素类型的矩阵时,我遇到了问题。

基本上我有一个模板类Matrix<T> , 其中T是该矩阵的元素类型。我正在使用 Boost-Operators 在 Matrix<T> 的实例之间定义运算符(例如逐元素添加),在 Matrix<T> 之间和 T (例如标量乘法),如果可能的话也在 Matrix<T> 之间和 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> .但是,现在我遇到了问题,那是两种不同的类型,我无法访问私有(private)成员。因此,我要么需要公开比我想要的更多的东西,要么找到一种不同的方式来做到这一点。

你会如何实现这样的事情?

完整代码

#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;
}

最佳答案

我会这样做:使用好友模板函数(参见 Operator overloading:成员(member)与非成员(member)之间的决定):

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

关于c++ - 具有混合类型的 Boost 运算符 - 转换和私有(private)成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21662099/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com