如何编写泛型代码计算Eigen矩阵或类元组对象的大小?
通用计算类数组/元组/Eigen矩阵元素总数的泛型实现
你的问题出在第一个模板的约束不够严格:当传入Eigen矩阵时,编译器会尝试实例化std::tuple_size_v<std::decay_t<T>>,但Eigen类型没有std::tuple_size的特化,这会触发硬编译错误,而非SFINAE的替换失败,导致第二个重载根本没机会被选中。
C++20 简洁实现(推荐)
用requires约束明确限定第一个模板仅对支持std::tuple_size的类型生效:
#include <tuple> #include <array> #include <Eigen/Core> // 匹配类数组/元组类型(std::tuple、std::array、std::pair等) template <typename T> constexpr auto size(const T&) requires requires { std::tuple_size_v<std::decay_t<T>>; } { return std::tuple_size_v<std::decay_t<T>>; } // 匹配所有Eigen矩阵/向量类型 template <typename Derived> constexpr auto size(const Eigen::MatrixBase<Derived>& mat) { return mat.size(); } // 可选:原生数组重载(std::tuple_size也支持原生数组,此重载更直观) template <typename T, std::size_t N> constexpr std::size_t size(const T (&)[N]) noexcept { return N; }
C++17 及更早版本兼容实现
用SFINAE结合void_t实现类型检测:
#include <tuple> #include <array> #include <type_traits> #include <Eigen/Core> // 检测类型是否支持std::tuple_size template <typename T, typename = void> struct has_tuple_size : std::false_type {}; template <typename T> struct has_tuple_size<T, std::void_t<decltype(std::tuple_size_v<std::decay_t<T>>)>> : std::true_type {}; // 仅对支持std::tuple_size的类型启用 template <typename T> constexpr std::enable_if_t<has_tuple_size<T>::value, std::size_t> size(const T&) { return std::tuple_size_v<std::decay_t<T>>; } // Eigen矩阵专属重载 template <typename Derived> constexpr std::size_t size(const Eigen::MatrixBase<Derived>& mat) { return mat.size(); } // 原生数组重载 template <typename T, std::size_t N> constexpr std::size_t size(const T (&)[N]) noexcept { return N; }
效果验证
- 传入
std::tuple{1, 2, 3}返回3 - 传入
std::array<int, 5>{}返回5 - 传入
Eigen::MatrixXd(3, 4)返回12 - 传入
int[10]{}返回10
内容的提问来源于stack exchange,提问作者jjcasmar
相关产品推荐
相关产品推荐

