哪个容器使用map或set还是别的? [英] which container to use map or set or else?

查看:150
本文介绍了哪个容器使用map或set还是别的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

If using std::map<std::string,object> to keep objects ordered by name, the map's value_type (std::pair<string,object>) is a convenient class which warrants useful functionality, e.g.

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);
}

到目前为止,还不错。我稍后扩展我的对象

So far, so good. I later extend my objects

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

,并通过 std :: map< std :: string,extended>
我可以定义。

and keep the extended objects ordered by name, too, via std::map<std::string,extended>. I may define.

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_object named_extended_object 与基本和派生类似。这是安全/可推荐吗?
或者,我考虑使用 std :: set (而不是 std :: map )类型
named_object 并重新定义

which essentially assumes that the data layouts of named_object and named_extended_object are exactly like that of base and derived. Is this safe/recommendable? Alternatively, I considered to use std::set (instead of std::map) with key types named_object and re-define

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

这种方法的问题是为了 std :: set: :find()一个对象,我必须提供不只是一个名称字符串,而是一个整个对象甚至扩展对象。根据 cpreference std :: set: :find()将在C ++ 14中解决这个问题(重载3& 4),但是我该怎么办呢?

The problem with this approach is that in order to std::set::find() an object, I must provide not just a name string, but a whole object or even extended object. According to cppreference, std::set::find() will have a resolution to this problem in C++14 (overloads 3&4), but what shall I do in the mean time?

推荐答案


地图的 value_type std :: pair< string,object> )是一个方便的类,它保证有用的功能。

the map's value_type (std::pair<string,object>) is a convenient class which warrants useful functionality

地图的 value_type std :: pair< const string,object>

reinterpret_cast 导致未定义的行为,当通过引用访问 named_extended_object 时,它违反了一些编译器调用的严格别名规则,并且可能导致程序错误if编译器使用基于类型的别名分析进行优化。不要使用 reinterpret_cast 。在手动的Liskov替换原则术语中, extended_object IS-A object ,所以可以替换 extended_object 其中对象是预期的,但 pair< T,extended_object>

The reinterpret_cast results in undefined behaviour when a named_extended_object is accessed through the reference, it violates what some compilers call "strict aliasing" rules, and can cause your program to misbehave if the compiler optimises using type-based alias analysis. Do not use reinterpret_cast like that. In handwavy Liskov Substitution Principle terms, extended_object IS-A object, so it's OK to substitute an extended_object where an object is expected, but pair<T, extended_object> IS-NOT-A pair<T, object> so cannot be used interchangeably.

我喜欢D Drmmr的回答,但是我不能使用如果你不想这样做,另一个选项是一个模板:

I like D Drmmr's answer, but if you don't want to do that, another option is a template:

template<typename Obj>
  void function(const std::pair<const std::string, Obj>&)
  {
    // ...
  }

这将接受 pair< const string,object> $ c> pair< const string,extended_object> arguments。如果模板的主体只尝试访问 object 中存在的成员,那么它将对两个参数类型都很好地工作。

This will accept pair<const string, object> and also pair<const string, extended_object> arguments. If the body of the template only tries to access the members that are present in object then it will work perfectly for both argument types.

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

If you don't want to expose that template to users of the function, then declare two overloads:

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

然后在实现文件中:

namespace {
  template<typename Obj>
    void function_impl(const std::pair<const std::string, Obj>&)
    {
      // common implementation ...
    }
}

void function(const named_object& no) { function_impl(no); }
void function(const named_extended_object& neo) { function_impl(neo); }

这篇关于哪个容器使用map或set还是别的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆