混合类型的Boost运算符-转换和私有成员
Boost operators with mixed types - conversion and private members
我正在使用Boost运算符来构造矩阵类。(玩具项目)。然而,当我想混合不同元素类型的矩阵时,我会遇到一些问题。
基本上,我有一个模板类Matrix<T>
,其中T
是该矩阵的元素类型。我使用Boost运算符来定义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>
的强制转换构造函数。然而,现在我有一个问题,那就是这是两种不同的类型,我无法访问私人成员。所以,我要么需要公开比我想公开的更多的东西,要么找到一种不同的方式。
你会如何实现这样的事情?
完整的代码
#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
来获得合理的结果类型(你可能想在那里引入你自己的特性来满足你的特定需求)
查看Coliru直播
相关文章:
- 从成员指针到整个结构/类的强制转换
- 将方法转换为调用该方法的成员函子对象会导致崩溃
- 从类成员函数到类 C 函数指针的转换
- 静态成员变量不会由 gettext 转换
- 指针类型类成员的动态强制转换的恒定性是什么?
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- 转换模板中的成员函数指针
- 传递可变参数时在成员初始值设定项列表中强制转换
- 将函数强制转换为成员函数
- 返回对常量结构(指针类型)成员的引用:明显的左值到右值转换
- 指向类成员函数的指针中存在类型转换错误
- 在不复制数据的情况下,将double数组转换为只有double成员的structs数组
- 指向数据成员转换的 Constexpr 指针
- 模板成员转换运算符,默认模板参数到与 TypeName 绑定的函数
- 将 TEXTRANGE 结构的 lpstrtext 成员转换为多字节字符集
- 模板成员转换运算符中的编译错误
- 类成员转换函数id
- std::unique_ptr结构成员转换为结构类型
- 将 Object int 数据成员转换为浮点数并划分会将奇怪的数据 cout 附加到控制台
- 怎样才能轻松地将枚举成员转换为int类型?