Dr.D.
Dr.D.

Reputation: 487

Undesired/Unexpected Compiler-Magic with Eigen and Ternary Operator

The following code unexpectedly assigns (0, -1, 0) instead of (0, 1, 0) as intended. Why? Any ideas?

#include <Eigen/Dense>

int main()
{
  const bool useFirst = false;

  // This is the original use-case.
  const Eigen::Vector3d vect1
    = useFirst ? -Eigen::Vector3d::UnitZ() : Eigen::Vector3d::UnitY();

  // This version is somewhat simplified, but exhibits the same problem.
  const Eigen::Vector3d unitZ(0.0, 0.0, 1.0), unitY(0.0, 1.0, 0.0);
  const Eigen::Vector3d vect2 = useFirst ? -unitZ : unitY;

  // FYI, this version does not compile (?).
  // const Eigen::Vector3d vect3
  //   = useFirst ? -unitZ : Eigen::Vector3d::UnitY();
}

Upvotes: 3

Views: 106

Answers (1)

chtz
chtz

Reputation: 18817

What happens is that -unitZ returns an expression template const CwiseUnaryOp<internal::scalar_opposite_op<double>, const Vector3d>, if unitZ is a Vector3d. In early versions of Eigen the 'else' parameter of the ?: operator got cast implicitly to that type and thus involuntarily negated it. This has been disallowed a while ago by making most constructors explicit -- so first of all, you should update your Eigen version.

For the actual solution: Avoid the ?: operator with Eigen expressions (use a simple if-else branch), or if not possible, explicitly cast the last parameters to the desired type:

typedef Eigen::Vector3d Vec3d;
const Vec3d vect1 = useFirst ? Vec3d(-Vec3d::UnitZ()) : Vec3d(Vec3d::UnitY());

Related question: Type error in ternary operator in Eigen

Upvotes: 4

Related Questions