从任意映射获取mapped_type的指针或引用
编辑:我已经找到并写下了问题的解决方案,但我没有回答这个问题,因为我的解决方案可能仍然不理想。
我正在编写一个小型库,旨在在地图的地图上执行例程,但是我在设计一组类模板时遇到了麻烦,这些模板将让我获得指向地图的指针或引用(取决于地图的 value_type 的第二类型) mapped_type,无论映射的类型如何(例如std::map、boost::ptr_map)。
为了进一步详细说明,我列出了一些输入类型和所需的输出类型。
Case Input Type Output Type
A std::map<int, std::map<int, int> > std::map<int, int>&
B std::map<int, boost::ptr_map<int, int> > boost::ptr_map<int, int>&
C boost::ptr_map<int, std::map<int, int> > std::map<int, int>* const
D std::map<int, std::map<int, int> >* std::map<int, int>&
E std::map<int, boost::ptr_map<int, int> >* boost::ptr_map<int, int>&
F boost::ptr_map<int, std::map<int, int> >* std::map<int, int>* const
我的代码通过了情况 A、B、D 和 E,但在情况 C 和 F 上失败了。这是我到目前为止所得到的。
template <class Map>
struct map_utils
{
template <class K>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(Map& m, const K k)
{
return m[k];
}
template <class K>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(const Map& m, const K k)
{
return const_cast<Map&>(m)[k];
}
};
template <class Map>
struct map_utils<Map*>
{
template <class T>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(Map* m, const T t)
{
return (*m)[t];
}
template <class T>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(const Map* m, const T t)
{
return const_cast<Map*>(m)->operator[](t);
}
};
我正在尝试使用 boost::mpl 来执行此操作,这就是我到目前为止所做的,但是使用两个版本的代码都遇到了相同的错误。
错误。
error: invalid initialization of reference of type ‘std::map<int, double>* const&’ from expression of type ‘boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::map_config<std::map<int, double>, std::map<int, void*, std::less<int>, std::allocator<std::pair<const int, void*> > >, true>, boost::heap_clone_allocator>::Ty_’
结构体的修改专门化用于处理不是指向映射的指针的左值。
template <class K>
static typename
boost::mpl::if_<
boost::is_pointer<
typename boost::remove_pointer<
typename Map::value_type
>::type::second_type
>,
typename boost::remove_pointer<
typename boost::remove_const<
typename Map::value_type
>::type
>::type::second_type,
typename boost::remove_pointer<
typename Map::value_type
>::type::second_type&
>::type
get(Map& m, const K k)
{
return m[k];
}
Edit: I've found and written up a solution to my problem but I've left the question unanswered since my solution may still not be ideal.
I'm writing a small library designed to perform routines on maps of maps, but I'm having trouble designing a set of class templates that will let me get a pointer or reference (depending on the second_type of the map's value_type) to a map's mapped_type, regardless of the type of the map (e.g. std::map, boost::ptr_map).
To elaborate further, I have tabulated some input types and desired output types.
Case Input Type Output Type
A std::map<int, std::map<int, int> > std::map<int, int>&
B std::map<int, boost::ptr_map<int, int> > boost::ptr_map<int, int>&
C boost::ptr_map<int, std::map<int, int> > std::map<int, int>* const
D std::map<int, std::map<int, int> >* std::map<int, int>&
E std::map<int, boost::ptr_map<int, int> >* boost::ptr_map<int, int>&
F boost::ptr_map<int, std::map<int, int> >* std::map<int, int>* const
My code passes cases A, B, D and E, but fails on cases C and F. Here is what I have so far.
template <class Map>
struct map_utils
{
template <class K>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(Map& m, const K k)
{
return m[k];
}
template <class K>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(const Map& m, const K k)
{
return const_cast<Map&>(m)[k];
}
};
template <class Map>
struct map_utils<Map*>
{
template <class T>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(Map* m, const T t)
{
return (*m)[t];
}
template <class T>
static typename
boost::remove_pointer<
typename Map::value_type
>::type::second_type&
get(const Map* m, const T t)
{
return const_cast<Map*>(m)->operator[](t);
}
};
I'm trying to use boost::mpl to do this, and this is what I've cooked up so far, but I get the same error using both versions of the code.
The error.
error: invalid initialization of reference of type ‘std::map<int, double>* const&’ from expression of type ‘boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::map_config<std::map<int, double>, std::map<int, void*, std::less<int>, std::allocator<std::pair<const int, void*> > >, true>, boost::heap_clone_allocator>::Ty_’
The modified specialization of the struct to deal with l-values that are not pointers to maps.
template <class K>
static typename
boost::mpl::if_<
boost::is_pointer<
typename boost::remove_pointer<
typename Map::value_type
>::type::second_type
>,
typename boost::remove_pointer<
typename boost::remove_const<
typename Map::value_type
>::type
>::type::second_type,
typename boost::remove_pointer<
typename Map::value_type
>::type::second_type&
>::type
get(Map& m, const K k)
{
return m[k];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
C和F似乎是错误的,映射类型不是boost::ptr_map。否则,听起来您可以使用完整的模板专业化来决定它是 std::map 还是 boost::ptr_map。像这样的东西:
C and F seems wrong, the mapped type isn't boost::ptr_map. Otherwise it sounds like you could just use full template specialization to decide whether it is an std::map or boost::ptr_map. Something like this:
我已经成功编译了代码,并在过程中大大简化了它,通过使用mapped_type typedef,如下所示:
只有方法的主体需要在上面问题中定义的结构的专门版本中进行更改,以便适应以及指向地图的指针。如果您想要完整的代码清单,请告诉我,我会将整个代码转储在这里。
I've got the code the compile successfully and greatly simplified it in the process, by using the mapped_type typedef like so:
Only the body of the methods needs to be changed in specialized versions of the struct defined in the question above in order to accommodate for pointers to maps as well. If you would like the entire code listing, let me know and I'll dump the entire thing here.