const转换为非const或非const转换为const

`const` to non-`const` or non-`const` to `const`

本文关键字:const 转换 或非      更新时间:2023-10-16

当同时存在const和非const getter时,下面的代码用于减少代码重复。它从非const创建const版本。我搜索了一下,很多人都说我应该从const创建一个非const版本。

我的想法是,如果我从const版本创建非const版本,与下面的代码相反,解引用返回的指针或引用最初是const可能是不安全的。我真的不确定,所以我要求澄清一下,什么是正确的"方向"?

template<typename T>
struct Constifier
{
  typedef T Type;
};
template<typename T>
struct Constifier<T &>
{
  typedef const T &Type;
};
template<typename T>
struct Constifier<T &&>
{
  typedef const T &&Type;
};
template<typename T>
struct Constifier<T *>
{
  typedef const T *Type;
};
template<typename F>
struct ReturnType;
template<typename R, typename ...Ts>
struct ReturnType<R (*)(Ts ...ts)>
{
  typedef R Type;
};
template<typename R, typename T, typename ...Ts>
struct ReturnType<R (T::*)(Ts ...ts)>
{
  typedef R Type;
};
template<typename T, typename F, typename ...Ts>
auto callConstVersion(const T *t, F f, Ts ...ts)
{
  return const_cast<typename Constifier<typename ReturnType<F>::Type>::Type>((const_cast<T *>(t)->*f)(ts...));
}
struct A
{
  A *p;
  A *get() {return p;}
  const A *get() const {return callConstVersion(this, static_cast<A *(A::*)()>(&A::get));}
};

您应该始终从const版本创建non-const版本,而不是相反。解释很简单,可以这样想:

只能在non-const对象上调用non-const getter。如果对象是non-const,你可以安全地在non-const方法中const_cast你的const getter。为什么?因为你只能在non-const对象上调用这个方法。

做相反的事情是不安全的,因为当在const中调用non-const方法时,你不能保证constness是保留的。