如果使用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); }