哪个容器使用map或set还是别的? [英] which container to use map or set or else?
问题描述
如果使用 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屋!