You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++20 Concepts实现Boost Geometry函数的回退运算符模板?

问题分析与解决方案

你的代码编译失败的核心原因是错误地显式指定了boost::geometry::within的模板参数,以及Concept的有效性检查逻辑不符合Boost Geometry的设计机制。

原代码的关键错误

Boost Geometry的within是通过ADL(参数依赖查找)+ 标签分发实现的函数模板,并非需要用户显式指定模板参数的版本。你在Concept中写boost::geometry::within<T1, T2>(t1, t2)会:

  1. 绕过库的重载解析机制,强制实例化一个可能不存在的模板特化;
  2. 在不支持的类型组合(比如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;
}

关键修正说明

  1. Concept的有效性检查:

    • 改为检查boost::geometry::within(t1, t2)的调用是否合法,同时验证返回值可转换为bool,完全遵循Boost Geometry的调用方式。
    • 这种检查是SFINAE友好的:对于不支持的类型组合,编译器会软失败,不会触发硬错误,从而允许回退版本被选中。
  2. 移除显式模板参数:

    • 在operator实现中直接调用boost::geometry::within(t1, t2),让ADL自动匹配库提供的正确重载,这是使用Boost Geometry算法的标准方式。
  3. 互斥的requires条件:

    • 两个operator模板的条件WithinCanBeCalled和!WithinCanBeCalled完全互斥,确保编译器在任何情况下都能唯一确定要调用的版本。

使用你提供的编译命令即可正常编译运行,输出结果为:within exists: 1 no within: 0。

内容的提问来源于stack exchange,提问作者Acave At

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:39:54