如何用C++20 Concepts实现Boost Geometry函数的回退运算符模板?
问题分析与解决方案
你的代码编译失败的核心原因是错误地显式指定了boost::geometry::within的模板参数,以及Concept的有效性检查逻辑不符合Boost Geometry的设计机制。
原代码的关键错误
Boost Geometry的within是通过ADL(参数依赖查找)+ 标签分发实现的函数模板,并非需要用户显式指定模板参数的版本。你在Concept中写boost::geometry::within<T1, T2>(t1, t2)会:
- 绕过库的重载解析机制,强制实例化一个可能不存在的模板特化;
- 在不支持的类型组合(比如
polygon和point的反向调用)下,触发硬编译错误,而非SFINAE友好的软失败,导致编译器无法回退到第二个operator模板。
修正后的代码
#include <iostream> #include <concepts> #include <boost/geometry.hpp> // 修正Concept:检查是否能通过ADL调用boost::geometry::within(t1, t2) template<typename T1, typename T2> concept WithinCanBeCalled = requires(const T1& t1, const T2& t2) { { boost::geometry::within(t1, t2) } -> std::convertible_to<bool>; }; struct Within { // 优先匹配:存在合法的within调用时使用 template <typename T1, typename T2> requires WithinCanBeCalled<T1, T2> bool operator()(const T1& t1, const T2& t2) const { return boost::geometry::within(t1, t2); // 不指定模板参数,依赖ADL } // 回退版本:没有合法的within调用时使用 template <typename T1, typename T2> requires (!WithinCanBeCalled<T1, T2>) bool operator()(const T1& t1, const T2& t2) const { return false; } }; int main() { using point_type = boost::geometry::model::d2::point_xy<double>; using polygon_type = boost::geometry::model::polygon<point_type>; polygon_type poly; boost::geometry::read_wkt( "POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)" "(4.0 2.0, 4.2 1.4, 4.8 1.9, 4.4 2.2, 4.0 2.0))", poly); point_type p(4, 1); Within within; std::cout << "within exists: " << within(p, poly) << " no within: " << within(poly, p) << std::endl; }
关键修正说明
Concept的有效性检查:
- 改为检查
boost::geometry::within(t1, t2)的调用是否合法,同时验证返回值可转换为bool,完全遵循Boost Geometry的调用方式。 - 这种检查是SFINAE友好的:对于不支持的类型组合,编译器会软失败,不会触发硬错误,从而允许回退版本被选中。
- 改为检查
移除显式模板参数:
- 在operator实现中直接调用
boost::geometry::within(t1, t2),让ADL自动匹配库提供的正确重载,这是使用Boost Geometry算法的标准方式。
- 在operator实现中直接调用
互斥的requires条件:
- 两个operator模板的条件
WithinCanBeCalled和!WithinCanBeCalled完全互斥,确保编译器在任何情况下都能唯一确定要调用的版本。
- 两个operator模板的条件
使用你提供的编译命令即可正常编译运行,输出结果为:within exists: 1 no within: 0。
内容的提问来源于stack exchange,提问作者Acave At
相关产品推荐
相关产品推荐

