我正在使用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
所以您失去了常态。
修改常量值是未定义的行为,
您的视图可以以通向UB的方式使用。
但是只要您不修改const对象,就可以了。“>
分成两类比较安全,因为它不会被滥用。