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

如何编写兼容Eigen Array/Matrix与nullopt的std::optional模板函数

如何修改C++模板函数以支持Eigen对象与std::nullopt混合传参?

原模板函数

template <typename Derived>
std::optional<Eigen::Array<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic>>
function1(const std::optional<Eigen::ArrayBase<Derived>>& opt1,
     const std::optional<Eigen::ArrayBase<Derived>>& opt2)
{

}

需求说明

需要让该模板函数能够接受以下任意组合的参数:

  • 两个Eigen Array/Matrix对象
  • 一个Eigen对象和一个std::nullopt
  • 两个std::nullopt

例如支持如下调用:

ArrayXXd a(4, 3);
ArrayXXd b(4, 3);
auto q = function1(a,b); // 直接传Eigen对象
auto r = function1(std::nullopt, b); // 混合传参
auto s = function1(std::nullopt, std::nullopt); // 传nullopt

已知可以编写如下非std::optional版本的模板函数作为参考:

template <typename Derived1, typename Derived2>
// 此处省略返回值,根据实际需求定义
function2(const Eigen::ArrayBase<Derived1>& opt1,
          const Eigen::ArrayBase<Derived2>& opt2)
{
}

请问如何修改原模板函数以满足需求?


修改方案

方案1:写重载函数(兼容旧版本C++,C++17及以上可用)

最直接的做法是给function1写几个重载,覆盖所有参数组合,同时把核心逻辑抽成内部函数复用:

// 核心实现:专门处理两个Eigen对象的业务逻辑
template <typename Derived1, typename Derived2>
std::optional<Eigen::Array<typename Derived1::Scalar, Eigen::Dynamic, Eigen::Dynamic>>
function1_impl(const Eigen::ArrayBase<Derived1>& arr1,
               const Eigen::ArrayBase<Derived2>& arr2)
{
    // 此处编写实际业务代码,例如数组运算、结果返回等
    return Eigen::Array<typename Derived1::Scalar, Eigen::Dynamic, Eigen::Dynamic>(arr1.rows(), arr1.cols());
}

// 重载1:两个参数都是Eigen对象
template <typename Derived1, typename Derived2>
auto function1(const Eigen::ArrayBase<Derived1>& arr1,
               const Eigen::ArrayBase<Derived2>& arr2)
{
    return function1_impl(arr1, arr2);
}

// 重载2:第一个是optional,第二个是Eigen对象
template <typename Derived1, typename Derived2>
auto function1(const std::optional<Eigen::ArrayBase<Derived1>>& opt1,
               const Eigen::ArrayBase<Derived2>& arr2)
{
    if (!opt1) return std::nullopt;
    return function1_impl(*opt1, arr2);
}

// 重载3:第一个是Eigen对象,第二个是optional
template <typename Derived1, typename Derived2>
auto function1(const Eigen::ArrayBase<Derived1>& arr1,
               const std::optional<Eigen::ArrayBase<Derived2>>& opt2)
{
    if (!opt2) return std::nullopt;
    return function1_impl(arr1, *opt2);
}

// 重载4:两个参数都是optional
template <typename Derived1, typename Derived2>
auto function1(const std::optional<Eigen::ArrayBase<Derived1>>& opt1,
               const std::optional<Eigen::ArrayBase<Derived2>>& opt2)
{
    if (!opt1 || !opt2) return std::nullopt;
    return function1_impl(*opt1, *opt2);
}

方案2:用C20特性简化(现代C推荐)

如果项目基于C++20或以上版本,可以用概念(Concepts)和类型萃取简化代码,自动识别参数类型:

#include <type_traits>

// 定义概念:判断类型是否为Eigen ArrayBase的派生类
template <typename T>
concept EigenArrayType = std::is_base_of_v<Eigen::ArrayBase<std::decay_t<T>>, std::decay_t<T>>;

// 定义概念:判断类型是否为包裹Eigen ArrayBase的optional
template <typename T>
concept OptionalEigenArrayType = requires(T opt) {
    typename T::value_type;
    requires EigenArrayType<typename T::value_type>;
    *opt;
};

// 辅助函数:提取参数值——Eigen对象直接返回,optional先判空再解包
template <EigenArrayType T>
const auto& get_value(const T& val) { return val; }

template <OptionalEigenArrayType T>
const auto& get_value(const T& opt) {
    if (!opt) throw std::invalid_argument("参数为nullopt");
    // 也可根据需求返回std::nullopt,需结合主函数逻辑调整
    return *opt;
}

// 主模板函数:支持Eigen对象或对应optional作为参数
template <typename T1, typename T2>
requires (EigenArrayType<T1> || OptionalEigenArrayType<T1>) &&
         (EigenArrayType<T2> || OptionalEigenArrayType<T2>)
std::optional<Eigen::Array<typename std::decay_t<T1>::Scalar, Eigen::Dynamic, Eigen::Dynamic>>
function1(const T1& arg1, const T2& arg2)
{
    // 检查是否存在nullopt参数
    if constexpr (OptionalEigenArrayType<T1> && !arg1) {
        return std::nullopt;
    }
    if constexpr (OptionalEigenArrayType<T2> && !arg2) {
        return std::nullopt;
    }

    // 提取有效值并执行核心逻辑
    const auto& arr1 = get_value(arg1);
    const auto& arr2 = get_value(arg2);

    // 此处编写业务逻辑
    return Eigen::Array<typename decltype(arr1)::Scalar, Eigen::Dynamic, Eigen::Dynamic>(arr1.rows(), arr1.cols());
}

补充说明

  • 方案1无需C++20特性,兼容旧编译器,逻辑直白易维护。
  • 方案2利用C20概念简化代码,扩展性更强,适合现代C项目。
  • 若需直接支持Eigen Matrix对象,可在逻辑中添加.array()转换,或新增对应概念与重载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:43:17