带有Eigen的C ++ Varaidic Tempate,带参数列表的重载函数给出了意想不到的结果

时间:2016-09-26 15:54:20

标签: c++ c++11 variadic-templates eigen

我一直在Eigen中测试C ++模板,并且在使用tempate和模板化参数列表时开发时遇到了问题。 根据以下示例,即使第3和第4个调用与原型完全匹配,也会为所有调用打印“功能2”。由于模糊性,似乎模板化参数列表优先。 现在有趣的是,只有当矩阵包含在“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

1 个答案:

答案 0 :(得分:2)

原因是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 << "funAB\n"; } template<typename... P> void fun(const A&, const P & ...) { std::cout << "funAP\n"; } 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

如果您明确要求&#34; Function1&#34;要在传递fun2时调用,只需将其写为参数(如在{{1}}实现中)。