哪个容器使用map或set?

时间:2014-05-01 12:48:03

标签: c++ c++11 map set

如果使用std::map<std::string,object>来保持按名称排序的对象,则地图value_typestd::pair<string,object>)是一个方便的类,可以保证有用的功能,例如

typedef std::map<std::string,object> object_map;
typedef typename object_map::value_type named_object;
void function(named_object const&);

// with the following possible use case
void foo(std::string const&name, object_map const &omap)
{
  auto obj=omap.find(name);
  if(obj==omap.end()) throw std::runtime_error("name not found");
  function(*obj);
}

到目前为止,这么好。我后来扩展我的对象

struct extended_object : object { /* more data */ };

并通过std::map<std::string,extended>保持按名称排序扩展对象。 我可以定义。

typedef std::map<std::string,extended_object> extended_object_map;
typedef typename extended_object_map::value_type named_extended_object;

不幸的是,我不能

void foo(std::string const&name, extended_object_map const& emap)
{
  auto eobj=emap.find(name);
  if(eobj==emap.end()) throw std::runtime_error("name not found");
  function(*eobj);        // cannot convert *eobj to const named_object&
}

现在,我的问题是如何解决这个问题的?我考虑使用reinterpret_cast<>

  function(reinterpret_cast<const named_object&>(*eobj));

基本上假设named_objectnamed_extended_object的数据布局与base和派生的数据布局完全相同。这是安全/值得推荐的吗? 或者,我考虑将std::set(而不是std::map)用于键类型 named_object并重新定义

struct named_extended_object : named_object { /* more data */ };

这种方法的问题在于,为了std::set::find()一个对象,我不仅要提供一个名称字符串,还要提供整个对象甚至是扩展对象。根据{{​​3}},std::set::find()将在C ++ 14中解决这个问题(重载3和4),但是我应该在同一时间做什么?

2 个答案:

答案 0 :(得分:1)

将您的功能更改为

void function(const std::string& name, const object& obj);

然后将其称为

auto obj = omap.find(name);
function(obj->first, obj->second);
// or
auto eobj = emap.find(name);
function(eobj->first, eobj->second);

答案 1 :(得分:1)

  

地图value_typestd::pair<string,object>)是一个方便的类,可以保证有用的功能

N.B。那是地图的value_type。它是std::pair<const string,object>

reinterpret_cast在通过引用访问named_extended_object时会导致未定义的行为,这违反了某些编译器调用的内容&#34;严格别名&#34;规则,如果编译器使用基于类型的别名分析进行优化,可能会导致程序行为异常。不要那样使用reinterpret_cast。在handwavy Liskov Substitution Principle术语extended_object IS-A object中,所以可以用extended_object代替object,但是{{1}因为IS-NOT-A pair<T, extended_object>不能互换使用。

我喜欢D Drmmr的答案,但如果你不想这样做,另一种选择是模板:

pair<T, object>

这将接受template<typename Obj> void function(const std::pair<const std::string, Obj>&) { // ... } pair<const string, object>个参数。如果模板的主体仅尝试访问pair<const string, extended_object>中存在的成员,那么它将适用于两种参数类型。

如果您不想将该模板公开给该函数的用户,请声明两个重载:

object

然后在实现文件中:

void function(const named_object&);
void function(const named_extended_object&);