如果使用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));
基本上假设named_object
和named_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),但是我应该在同一时间做什么?
答案 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_type
(std::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&);