考虑以下玩具示例,在此我声明一个类,该类封装了 boost库中的ublas
:
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <iostream>
namespace ublas = boost::numeric::ublas;
class UblasEncapsulated {
public:
ublas::compressed_matrix<float>::reference operator()(int i, int j){
std::cout << "Non const reference" << std::endl;
MtrUpdated_ = true;
return mtr_(i, j);
}
ublas::compressed_matrix<float>::const_reference operator()(
int i, int j) const {
std::cout << "Const reference" << std::endl;
return mtr_(i, j);
}
UblasEncapsulated() { MtrUpdated = false; }
private:
ublas::compressed_matrix<float> mtr_(3, 3);
bool MtrUpdated_;
};
int main() {
UblasEncapsulated foo;
foo(2, 0) = 1.0f;
float const foo_float = foo(2, 0);
return 0;
}
我期待着输出
Non constant reference
Constant reference
但是我得到了
Non constant reference
Non constant reference
我究竟做错了什么?如何正确跟踪
mtr_
的值何时可以更改? 最佳答案
foo
是非常量的,因此将调用foo.operator()
的非常量版本。它返回的值的使用方式无关紧要。
如果您真的想知道MtrUpdated_
仅在实际分配了元素的情况下设置为true,则需要使用代理类:
class UblasEncapsulated {
public:
class proxy {
public:
proxy(UblasEncapsulated* ptr, int i, int j)
: ptr_(ptr), i_(i), j_(j)
{}
proxy& operator=(float f) {
ptr_->MtrUpdated_ = true;
ptr_->mtr_(i_, j_) = f;
return *this;
}
operator float() {
return ptr_->mtr_(i_, j_);
}
private:
UblasEncapsulated* ptr_;
int i_;
int j_;
};
proxy operator()(int i, int j) {
return proxy(this, i, j);
}
ublas::compressed_matrix<float>::const_reference operator() (int i, int j) const {
return mtr_(i, j);
}
UblasEncapsulated()
: mtr_(3, 3),
MtrUpdated_(false)
{}
private:
ublas::compressed_matrix<float> mtr_;
bool MtrUpdated_;
};
Live Demo
请注意,如果可以避免使用代理类,则应避免使用它,因为它不能与
auto
或模板参数推导之类的东西很好地配合使用。关于c++ - 封装ublas并将const引用重载到operator(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49374096/