C++ 具有特征的瓦拉迪试时,带有参数列表的重载函数会产生意外的结果

C++ Varaidic Tempate with Eigen, overloading functions with parameter list gives unexpected result

本文关键字:函数 列表 重载 结果 意外 参数 特征 C++      更新时间:2023-10-16

我一直在 Eigen 中测试C++模板化,并且在使用模板和模板化参数列表进行开发时遇到了问题。根据以下示例,为所有调用打印"函数 2" - 即使第 3 次和第 4 次调用与原型完全匹配。由于歧义,模板化参数列表似乎优先。现在有趣的是,这只发生在矩阵包装在"Eigen::MatrixBase"中时,如果我直接发送矩阵,这不是问题。但这对于正在使用的表达式模板来说并不是最佳的。

有人可以在使用MatrixBase时解释一下原因以及解决方法是什么?我知道给一个函数一个不同的名称可以解决问题,但这样函数就会失去通用性。有没有更好的解决方法?

谢谢你的时间!

显示效果的最小示例:

typedef Eigen::Matrix<float, 2, 2> QType;
typedef Eigen::Matrix<float, 1, 1> UType;
template <typename... ParamsType>
void fun(const Eigen::MatrixBase<QType> &Q,
         const Eigen::MatrixBase<UType> &U,
         const ParamsType & ...params)
{
  cout << "Function 1" << endl;
}
template <typename... ParamsType>
void fun(const Eigen::MatrixBase<QType> &Q,
         const ParamsType & ...params)
{
  cout << "Function 2" << endl;
}
template <typename... ParamsType>
void fun2(const QType &Q,
          const UType &U,
          const ParamsType & ...params)
{
  cout << "Function 1" << endl;
}
template <typename... ParamsType>
void fun2(const QType &Q,
          const ParamsType & ...params)
{
  cout << "Function 2" << endl;
}
int main(int argc, char *argv[])
{
  QType Q = QType::Random();
  UType U = UType::Random();
  int param = 0;
  fun(Q);
  fun(Q, param);
  fun(Q, U);
  fun(Q, U, param);
  fun2(Q);
  fun2(Q, param);
  fun2(Q, U);
  fun2(Q, U, param);
  return 0;
}

输出:

Function 2
Function 2
Function 2
Function 2
Function 2
Function 2
Function 1
Function 1

原因是UTypeMatrixBase<UType>不同,但它继承自它。这意味着将U作为可变参数传递更接近函数标头(抱歉无法引用标准中的相应部分(。请参阅此简化示例,该示例也说明了差异:

#include <iostream>
class A {};
class B {};
class C : public A { };
class D : public B { };
template<typename... P>
void fun(const A&, const B&, const P & ...p)
{
    std::cout << "funABn";
}
template<typename... P>
void fun(const A&, const P & ...)
{
    std::cout << "funAPn";
}
int main()
{
    A a;
    B b;
    C c;
    D d;
    fun(a,b); // funAB
    fun(c,d); // funAP, because d only inherits from B
}

如果您明确希望在传递UType时调用"Function1",只需将其编写为参数(如在fun2实现中一样(。