根据我的经验,在const和非const版本的成员方法中使用相同的代码是一种常见的现象。避免复杂方法的代码重复的一种方法是使用const_cast
来删除非const版本中的常量,例如在Effective C ++(第3项)中推荐的Scott Meyers。然而,这对于可能只返回指针的非常短的方法是没有益处的 - 当然,在这种情况下复制不是那么有问题。这仍然让我想知道是否存在没有关键字或等效替换铸件的原因。
我可以想象使用以下声明:
autoconst Data* const getData() autoconst;
当然这个关键字不会添加任何以前无法实现的功能,但我认为它会很好。据我所知,auto关键字同样不允许任何新的结构,但在代码中是一个很好的简化 - 不可否认的是更广泛(如果我错了请纠正我)。
我的问题是,这是否与C ++标准中的某些规则相冲突 - 如果不是,那么它是否只是没有用到实现。
答案 0 :(得分:5)
有一种标准化的方式,但没有多少人使用它:
class X
{
T data;
public:
template<typename autoconst>
friend /* or static */ auto get_data(autoconst& that) -> decltype(that.data)
{
// process that and return that.data
}
};
它被称为get_data(x)
而不是x.get_data()
,但是一个实现同时提供const
和非const
用法,而不使用强制转换或其他非类型安全技术。< / p>
还可以使用成员函数来启用成员调用语法。这将需要const
和非const
变体,但不会重复“进程that.data
”步骤,因为两者都可以委托给朋友模板。
更完整的例子:
template<typename T>
class HyperMatrix
{
int rows, cols, planes;
T* data;
/* they get initialized somehow */
public:
template<typename ThisType>
friend /* or static */ auto at(ThisType& that, int const r, int const c, int const p) -> decltype(*(that.data))
{
// argument validation logic not being duplicated
if (r < 0 || r >= that.rows) throw index_exception();
if (c < 0 || c >= that.cols) throw index_exception();
if (p < 0 || p >= that.planes) throw index_exception();
// complicated indexing expression, also not duplicated
const index = (p * that.rows + r) * that.cols + c;
return that.data[index];
}
// these enable a more natural syntax than at(hymatrix, 1, 2, 3)
T& operator()(int const r, int const c, int const p)
{ return /* ThisType = HyperMatrix<T> */ at(this, r, c, p); }
const T& operator()(int const r, int const c, int const p)
{ return /* ThisType = const HyperMatrix<T> */ at(this, r, c, p); }
};
示例,没有简单的解决方法:
template<typename T>
class BalancedJumpTable
{
public:
template<typename ThisType, typename Functor>
friend /* or static */ auto for_each(ThisType& that, Functor f)
{
// complicated code for walking the tree not duplicated
// deep inside loops and recursive calls, we find
f(that->something());
// maybe there's even some filtering logic which causes only
// only certain items to be passed to the callback
}
template<typename Functor>
void for_each(Functor f)
{ return for_each(this, f); }
void for_each(Functor f) const
{ return for_each(this, f); }
};
答案 1 :(得分:-3)
我没有按你的需要出售。事实上,如果您发现自己反复抛弃const
,我的代码完全正确无法销售。
考虑您可以将非const
个对象传递给期望const
个对象的函数。参数上的const
只是被调用者不会改变对象的合同 - 它既可以也可以不会。如果它确实改变了它,传递const
对象是一个错误(其错误是有争议的,但在某处有错误)。如果它没有改变它,你可以传递任何东西。
我不确定除了尝试使用正确的合同重写代码之外还有什么要说的,或者如果您不能打扰,根本就不要使用任何const
。