围绕常量指针和非常量指针的统一包装
Unified wrapper around const and non-const pointers
我在C++项目中使用GNU科学库。为了方便起见,我想将gsl_vector*
透明地封装在C++类中(以添加一堆特定于域的函数并简化接口)。但我对如何处理const gsl_vector*
感到困惑。让我解释一下。让我从这个极简主义包装开始。
class Vector {
gsl_vector* vector_;
public:
Vector(gsl_vector* vector): vector_(vector) {}
double& operator()(int i) {
return *gsl_vector_ptr(vector_, i);
}
};
进一步假设,我有两个函数。一个定义如下:
int f(Vector& x) {
\ do some math, e.g. x(0) = 0.0;
return 0;
}
另一个是回调函数,它必须使用GSL类型,定义如下:
int gsl_f(gsl_vector* x) {
Vector xx(x);
return f(xx);
}
这很好用。现在,假设回调有一个常量签名:
int gsl_f(const gsl_vector* x);
然后我可以相应地重新定义我的Vector
类和f
函数:
class Vector {
const gsl_vector* vector_;
public:
Vector(const gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_const_ptr(vector_, i);
}
};
int f(const Vector& x) {
\ do some math
return 0;
}
同样有效。现在,我希望我的包装器类能够适应这两种情况。例如,我希望能够执行以下操作,保留const的安全性:
int f(const Vector& x, Vector& y) {
\ do some math
return 0;
}
int gsl_f(const gsl_vector* x, gsl_vector* y) {
Vector yy(y);
return f(x, yy);
}
我可以通过使用具有两个指针(const和nonconst)的Vector
,并记住它是从const还是nonconst成员初始化的。我的问题是,我可以在没有运行时检查的情况下完成它吗?毕竟,在编译时所有的信息都在那里。
提案(不太好,但应该有效):
class Vector {
gsl_vector* vector_;
const gsl_vector* const_vector_;
public:
Vector(const gsl_vector* vector): vector_(nullptr), const_vector_(vector) {}
Vector(gsl_vector* vector): vector_(vector), const_vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(const_vector_, i);
}
double& operator () (int i) {
return *gsl_vector_ptr(vector_, i);
}
};
第二种可能性:
class Vector {
private:
gsl_vector* vector_;
Vector(gsl_vector* vector): vector_(vector) {}
public:
static const Vector* Create (const gsl_vector* vector) {
return new Vector (const_cast<Vector *> vector);
}
static Vector* Create (gsl_vector* vector) {
return new Vector (vector);
}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
double& operator () (int i) {
return *gsl_vector_ptr(vector_, i);
}
};
组合这两个类应该可以按预期工作,你尝试过吗?
class Vector {
gsl_vector* vector_;
public:
Vector(gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
double& operator()(int i) {
return *gsl_vector_ptr(vector_, i);
}
operator const_Vector()
{
return const_Vector(vector_);
}
};
class const_Vector {
const gsl_vector* vector_;
public:
const_Vector(const gsl_vector* vector): vector_(vector) {}
const double& operator()(int i) const {
return *gsl_vector_ptr(vector_, i);
}
};
函数签名需要这样看:
int f(const_Vector& x, Vector& y) {
\ do some math
return 0;
}
这遵循类似于迭代器和const_iterator的方案。
也许你有一种情况,这是行不通的,。你应该发布这种情况,我们可以尝试解决它。
您还可以使用某种类型的继承,将指针指向数据。根据输入指针类型,可以使用进一步的模板创建重载函数,返回一个或第二个版本。
class JSONChannelFullConfigConst:
public JSONObjectRenderer {
public:
JSONChannelFullConfigConst(const uint8_t * channel_id,
const sensors_single_channel_config_t * cfg) :
j_channel_id(channel_id),
j_cfg(cfg) {
}
private:
const uint8_t * const j_channel_id;
const sensors_single_channel_config_t * const j_cfg;
void renderFields(rlf::UcOstreamBase& os) const;
public:
uint8_t getId() const {
return *j_channel_id;
}
};
class JSONChannelFullConfig:
public JSONChannelFullConfigConst,
public JSONObjectParser {
public:
JSONChannelFullConfig(uint8_t * channel_id, sensors_single_channel_config_t * cfg) :
JSONChannelFullConfigConst(channel_id, cfg),
j_channel_id(channel_id),
j_cfg(cfg) {
}
void setId(uint8_t id) {
*j_channel_id = id;
}
private:
uint8_t * const j_channel_id;
sensors_single_channel_config_t * const j_cfg;
virtual bool parseNameValuePair(const char * name, rlf::UcIstream & value);
};
相关文章:
- 将常量指针引用绑定到非常量指针
- 如何使用数据对象上的常量指针初始化类
- C++中的指针和常量问题不大
- 为什么我收到"从常量指针到指针的转换无效?
- 当成员值从指针更改为非指针时,C++常量问题
- 使用双指针传递 2D 常量数组
- C++/QT:使用指向私有成员的常量指针作为只读数据共享
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 模板推导:为什么函数指针模板定义在常量和/或引用时不匹配?
- 初始化指针的常量向量
- 区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
- 什么是常量指针常量引用类型的参数?(const X* const & p)
- 无法将"常量指针常量"传递给常量引用
- C++:如何创建一个临时对象,包含一个指针 - 常量或非常量,具体取决于上下文
- 具有函数指针常量数组的 C++ 模板化静态类
- 这个constexpr整数不是空指针常量吗
- 使指针常量C++
- C++11在stl容器中共享指针常量
- 空指针常量转换为右值
- 在参考 (T&) 和常量指针 (T* 常量) 之间进行选择