我正在编写一些包含std :: unordered_map类型的C代码,我希望隐藏底层类型并将其作为另一种类型呈现 . 更具体地说,我想用std :: unordered_map用另一种类型包装std :: pair . 为了论证,让我们假设包装器看起来像这样......
template <typename ActualT >
class wrapper final
{
private:
ActualT actual_;
public:
//Some constructors...
typename ActualT::first_type & get_first()
{
return actual_.first;
}
typename ActualT::second_type & get_second()
{
return actual_.second;
}
};
我的理由是,由于包装类只有一个成员,它是包装的确切类型,将引用从原始类型转换为包装类型应该没问题,但结构的类型兼容性表明成员应具有要兼容的类型的相同类型和名称 . 以这种方式使用类型惩罚可能会导致未定义的行为或对齐问题吗?
using my_map = std::unordered_map < int, int >;
my_map m;
//Do some inserts...
reinterpret_cast<wrapper<typename my_map::value_type>&>(*m.find(10)).get_second() = 1.0;
我希望允许客户端代码访问 Map 的条目,而不知道 Map 返回的对 . 我还想编写一个自定义的前向迭代器,因此我需要返回对该条目的引用 . 将对该引用的引用转换为对作为包装器的类的引用会被认为是危险的吗?
是否有更好的方法来实现这一目标?
2 回答
这绝对是未定义的行为 .
认真重新考虑你的优先事项 .
表格的一些免费功能
将为你提供有意义的名字 .
如果必须使用不同的名称包装标准库,只需使用非显式构造函数,并存储引用 .
如果你真的需要迭代器去取消引用
entry
你可以 . 但是你可以隐式地从Map::iterator::operator*
返回的Map::reference
实例化entry
,你不需要自定义迭代器 .所以你可以清理它,但我不建议:
以上内容有效地隐藏了您 class 用户的
pair
. 它不处理异常(例如find()
返回end()
),并且不保证生命周期 . 's marginally better than what you have because it doesn' t要求reinterpret_cast
为不相关的类型 .然而,
map
,unordered_map
,set
等将返回迭代器存储为对只是库的一部分 - 它's the canonical form and I don' t看到了屏蔽人们的好处 .