自定义引用包装器的 const 正确性

const correctness for custom reference wrapper

我正在使用 boost::variant 在跨网络发送数据时实现类型擦除。当数据到达客户端或服务器时,我正在检查其结构以检索基础信息,并在结构与 API 中商定的结构不匹配时报告错误。为此,我创建了一个轻量级引用包装器,它包含对变体的引用,并为结构检查和类型转换提供方便的接口。

using value_t = boost::make_recursive_variant< /*types, some of them recursive*/ >::type;

class view_t {
public:
  /*non-const methods to access value_*/
private:
  value_t& value_;
};

class cview_t {
public:
  /*const methods to access value_*/
private:
  const value_t& value_;
};

view_t   view(value_t& v){ return v; }
cview_t cview(const value_t& v){ return v; }
cview_t cview(value_t&& v) = delete;
cview_t cview(const value_t&& v) = delete;

不幸的是,这个接口被证明很麻烦,因为每个具有 view 成员的聚合类型都需要遵循相同的 const/non-const 拆分。我想知道将这两个 类 合并到一个视图中并在创建视图的方法中使用 const_cast 是否合法:

class view_t {
public:
  /*const and non-const methods to access value_*/
private:
  value_t& value_;
};

      view_t view(value_t& v){ return v; }
const view_t cview(const value_t& v){ return const_cast<value_t&>(v); }
const view_t cview(value_t&& v) = delete;
const view_t cview(const value_t&& v) = delete;

返回 const 对象大多是无用的,因为

auto /*view_t*/ my_view = cview(some_value); // legal

所以你失去了常量。

修改 const 值是未定义的行为,

您的观点可以用于导致 UB。

但是只要你不修改const对象,你就是"fine"。

拆分为 2 类 更安全,因为它不会被滥用。