使用哪个容器映射或设置或其他



如果使用std::map<std::string,object>按名称对对象进行排序,则映射的value_type(std::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));

其本质上假设CCD_ 6和CCD_。这安全/值得推荐吗?或者,我考虑将std::set(而不是std::map(与密钥类型一起使用named_object和重新定义

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

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

将函数更改为

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

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

N。B.这是而不是地图的value_type。是std::pair<const string,object>

当通过引用访问named_extended_object时,reinterpret_cast会导致未定义的行为,这违反了一些编译器所称的"严格别名"规则,并且如果编译器使用基于类型的别名分析进行优化,可能会导致程序行为不端。不要那样使用reinterpret_cast。在手工的Liskov替换原理术语中,extended_object IS-A object,因此可以在预期object的情况下替换extended_object,但pair<T, extended_object> IS-NOT-A pair<T, object>因此不能互换使用。

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

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

然后在实现文件中:

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

最新更新