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

判断三角形退化的Eigen模板不支持固定尺寸矩阵如何修复

错误原因
  • 代码中使用运行时if判断矩阵列数,而C++编译阶段会实例化所有分支的代码。当传入固定列数为2的矩阵时,cols() == 3分支的代码也会被编译,该分支中尝试将2列的行向量赋值给固定尺寸Matrix<scalarType, 1, 3>,触发Eigen的静态尺寸校验报错。
  • 动态尺寸矩阵不会触发该问题,是因为动态尺寸的校验在运行时执行,而cols()==3的分支运行时不会进入,因此不会触发运行时错误。
解决方案

下面给出两种常用的兼容方案:

方案1:C++17及以上版本使用if constexpr做编译期分支剪枝

该方案代码最简洁,编译期会根据输入矩阵的固定尺寸自动剪枝不符合的分支,不会实例化错误分支的代码:

#include <Eigen/Core>
#include <iostream>

template<typename Derived>
bool nondegenerate(const Eigen::PlainObjectBase<Derived>& triangle) {
  using scalarType = typename Derived::Scalar;
  constexpr int Cols = Derived::ColsAtCompileTime;

  if constexpr (Cols == 2 || Cols == Eigen::Dynamic) {
    if (triangle.cols() == 2) {
      const auto v1 = triangle.row(1) - triangle.row(0);
      const auto v2 = triangle.row(2) - triangle.row(0);
      return static_cast<bool>(v1(0) * v2(1) - v1(1) * v2(0));
    }
  }

  if constexpr (Cols == 3 || Cols == Eigen::Dynamic) {
    if (triangle.cols() == 3) {
      const auto v1 = triangle.row(1) - triangle.row(0);
      const auto v2 = triangle.row(2) - triangle.row(0);
      return static_cast<bool>(v1.cross(v2).norm());
    }
  }

  std::cerr << "Undefined input." << std::endl;
  return false;
}

方案2:C++11及更早版本使用编译期分发实现兼容

如果编译器不支持C++17,可以借助Eigen自带的Int2Type工具把不同维度的处理逻辑拆分为重载函数,实现编译期分支分发:

#include <Eigen/Core>
#include <iostream>

// 处理2维三角形
template<typename Derived>
bool nondegenerate_impl(const Eigen::PlainObjectBase<Derived>& triangle, Eigen::Int2Type<2>) {
  const auto v1 = triangle.row(1) - triangle.row(0);
  const auto v2 = triangle.row(2) - triangle.row(0);
  return static_cast<bool>(v1(0) * v2(1) - v1(1) * v2(0));
}

// 处理3维三角形
template<typename Derived>
bool nondegenerate_impl(const Eigen::PlainObjectBase<Derived>& triangle, Eigen::Int2Type<3>) {
  const auto v1 = triangle.row(1) - triangle.row(0);
  const auto v2 = triangle.row(2) - triangle.row(0);
  return static_cast<bool>(v1.cross(v2).norm());
}

// 处理动态尺寸矩阵的运行时分发
template<typename Derived>
bool nondegenerate_impl(const Eigen::PlainObjectBase<Derived>& triangle, Eigen::Int2Type<Eigen::Dynamic>) {
  if (triangle.cols() == 2) {
    return nondegenerate_impl(triangle, Eigen::Int2Type<2>());
  } else if (triangle.cols() == 3) {
    return nondegenerate_impl(triangle, Eigen::Int2Type<3>());
  } else {
    std::cerr << "Undefined input." << std::endl;
    return false;
  }
}

// 对外调用入口
template<typename Derived>
bool nondegenerate(const Eigen::PlainObjectBase<Derived>& triangle) {
  return nondegenerate_impl(triangle, Eigen::Int2Type<Derived::ColsAtCompileTime>());
}

两种方案都可以同时兼容固定尺寸、动态尺寸的Eigen矩阵输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 19:15:06