旧CGAL代码升级至CGAL-4.5编译报错:sizeof应用无效
问题原因分析
这个编译错误的核心是CGAL从4.1到4.5版本,对Search_traits_adapter所依赖的property map的类型要求发生了变更。
在CGAL 4.1中,Search_traits_adapter兼容boost::readable_property_map_tag,因为当时的内部实现只需要从property map中读取数据即可。但到了CGAL 4.5,官方收紧了对property map的要求:Search_traits_adapter强制要求property map的category必须是boost::lvalue_property_map_tag。这一点从报错信息里的静态断言可以直接看出来:
BOOST_STATIC_ASSERT( ( boost::is_same< boost::lvalue_property_map_tag,
这个断言是用来检查你的property map的category是否为lvalue_property_map_tag,当你使用readable_property_map_tag时,断言失败,触发编译错误。
为什么CGAL会做这个变更?因为后续版本的Kd-tree相关组件(比如Kd_tree和Fuzzy_iso_box)在内部操作中,需要能够获取到指向原始数据的左值引用(即使是const的),而readable_property_map_tag只保证可读,不保证能提供左值引用,无法满足内部实现的需求。
适配CGAL 4.5的解决方案
最直接且经过验证的解决方案就是保持使用boost::lvalue_property_map_tag作为你的My_point_property_map的category,就像你已经测试的那样:
class My_point_property_map { public: typedef Point_2 value_type; typedef const value_type& reference; typedef const Point_and_int& key_type; typedef boost::lvalue_property_map_tag category; // 保留这个即可 };
你的get函数返回的是const Point_2&,完全符合lvalue_property_map_tag的要求(它允许返回const左值引用),所以这个修改不会影响代码的功能,同时能完美兼容CGAL 4.5及以后的版本。
如果你出于某种原因一定要使用readable_property_map_tag,那需要重新设计property map的实现,或者考虑使用CGAL提供的其他适配器(比如CGAL::Identity_property_map,如果你的数据结构不需要额外映射的话),但实际上这个方案完全没必要——因为你当前的实现已经满足lvalue_property_map_tag的要求,直接保留该标签是最优解。
内容的提问来源于stack exchange,提问作者natan

