2

I've designed a class with two overloaded functions taking Eigen data structures of different sizes.

The code compiles as long as I'm passing lvalues but if I pass an rvalue I get a compiler error ambiguity because both return the same ConstantReturnType.

Here is a MWE:

#include <iostream>
#include <Eigen/Geometry>

using namespace std;
using namespace Eigen;


class MyOverloadAmbiguity {
public:
  void ambiguousOverload(const Eigen::Vector3d& v) {
    std::cout << "I'm taking a Vector3d\n";
  }
  void ambiguousOverload(const Eigen::Vector4d& v){
    std::cout << "I'm taking a Vector4d\n";
  }
};


int main()
{
  MyOverloadAmbiguity moa;
  Eigen::Vector3d v3;

  moa.ambiguousOverload(v3); // <--- this works
  moa.ambiguousOverload(Eigen::Vector4d::Zero()); // <--- this doesn't

  return 0;
}
main.cpp:26: error: call of overloaded ‘ambiguousOverload(const ConstantReturnType)’ is ambiguous
   26 |   moa.ambiguousOverload(Eigen::Vector4d::Zero());
      |                                                ^
    main.cpp:10:8: note: candidate: ‘void MyOverloadAmbiguity::ambiguousOverload(const Vector3d&)’
   10 |   void ambiguousOverload(const Eigen::Vector3d& v) {
      |        ^~~~~~~~~~~~~~~~~
main.cpp:13:8: note: candidate: ‘void MyOverloadAmbiguity::ambiguousOverload(const Vector4d&)’
   13 |   void ambiguousOverload(const Eigen::Vector4d& v){
      |        ^~~~~~~~~~~~~~~~~

Is there a way to avoid this without explicitly changing the function names or add extra arguments just to avoid the ambiguity?

mcamurri
  • 153
  • 11
  • You said *code compiles for lvalues*. Are you sure about that? If you write: `auto i = Eigen::Vector4d::Zero();moa.ambiguousOverload(i);` where `i` is an lvalue, the code won't compile and gives the same ambiguity error. Or are you referring to passing `v3` when you did `moa.ambiguousOverload(v3);`. – Jason Mar 11 '22 at 12:08
  • Yes I meant when you explicitly assign to `v3`. I haven't tried the `auto`. – mcamurri Mar 11 '22 at 12:14
  • `using namespace std;` `using namespace Eigen;` bad idea. don't pull everything to the global namespace. – JHBonarius Mar 11 '22 at 14:30
  • Are your `ambiguousOverload` methods doing something substantially different? Otherwise, why not take a `MatrixBase const&` as argument? – chtz Mar 13 '22 at 09:12

1 Answers1

3

Your example does not work because the return type of Zero() is not a matrix, but an Eigen expression.

Thus, one way of achieving what you want with minimal changes is to use explicit matrix evaluation:

moa.ambiguousOverload(Eigen::Vector4d::Zero().eval());

You may also want to consider writing functions taking Eigen expressions as parameters (rather than explicit matrices), as an alternative solution.

L. Bruce
  • 170
  • 7
  • Can you elaborate more on the second solution? You mean a function that takes a `ConstantReturnType` explicitly? I wouldn't know how to distinguish between the sizes. – mcamurri Mar 11 '22 at 18:12