mercredi 2 novembre 2016

A simple * binary operator does not compile with an extended Eigen::Matrix type but works with its own operator

Following the example for extension of Eigen::Types here on Inheriting From Matrix, I created the following, a slight variation of the example:

class MyType : public Eigen::Vector3d {
public:
  MyType(void) : Eigen::Vector3d() {}
  template<typename OtherDerived> // MyType ctor from Eigen expressions
  MyType(const Eigen::MatrixBase<OtherDerived>& other)
    : Eigen::Vector3d(other) {}

  // ... operator= as in the example, not shown to save some space ...

  // ONLY NEW CODE: a new binary operator ^ returning Matrix3d
  template<typename OtherDerived>
  Eigen::Matrix3d operator^ (const Eigen::MatrixBase<OtherDerived>& other) {
    return Eigen::Matrix3d{ *this * other.transpose() };
  }
};

The new binary operator ^ does its job only conditionally as shown below:

MyType t1; t1.setRandom(); std::cout << "t1 is:\n" << t1 << std::endl;
MyType t2; t2.setRandom(); std::cout << "t2 is:\n" << t2 << std::endl;

Eigen::Matrix3d t3 = t1 ^ t2; std::cout << "t3 is:\n" << t3 << std::endl; // works
const double fac1{ 10.0 }; // invoke using multiplication factors
t3 = t1 ^ t2*fac1; // and t1 ^ fac1*t2 also works, output is correct

t3 = t1*fac1 ^ t2; // does not compile. Neither does t1*fac1 ^ t2.

I can use the standard * binary operator with a scalar and a Vector3d as operands (supported by Eigen). But it works only on the second operand of my new ^ binary operator. Based on the operator precedence, and perhaps some ADL (argument-dependent lookup), I expect the compiler to sort them out. Now here is the compiler error message (in code style for readability):

myCode.cpp(43) : error C2676: binary '^' :
  'const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>,const Derived>'
  does not define this operator or a conversion to a type acceptable to the 
  predefined operator with
    [   Derived=Eigen::Matrix<double,3,1,0,3,1>    ]

Am I to infer that the compiler thinks somehow * in t1*fac1 is a unary operator? How come this was not a problem when it was applied on t2 whose type is exactly the same as that of t1. Tried enclosing between parantheses so: (fac1*t1) ^ t2, but did not work. I also defined my own operator* (const double&) with a scalar and MyType as operands, but the above line of code had exactly the same compilation error.

Could this be an Eigen or a compiler bug? I am using MS Visual C++ 2015. Am I missing something simple? Any light you can shed on the issue is appreciated.

Aucun commentaire:

Enregistrer un commentaire