2017-05-23 1 views
3

Der folgende Code weist unerwartet (0, -1, 0) statt (0, 1, 0) wie vorgesehen zu. Warum? Irgendwelche Ideen?Unerwünschte/unerwartete Compiler-Magic mit Eigen- und Ternäroperator

#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(); 
} 
+0

Auf meinem Rechner kompiliert die 'vect1' Version nicht, aber die' vect2' Version erzeugt (0, 1, 0) wie vorgesehen. – Cholts

Antwort

3

Was passiert ist, dass -unitZ gibt eine Ausdrucksvorlage const CwiseUnaryOp<internal::scalar_opposite_op<double>, const Vector3d>, wenn unitZ ein Vector3d ist. In früheren Versionen von Eigen wurde der 'else' -Parameter des ?:-Operators implizit auf diesen Typ umgewandelt und somit unfreiwillig negiert. Dies wurde vor einiger Zeit nicht erlaubt, indem die meisten Konstruktoren explicit gemacht wurden - zuerst sollten Sie Ihre Eigen-Version aktualisieren.

Für die eigentliche Lösung: Vermeiden Sie den ?: Operator mit Eigen Ausdrücken (einen einfachen if-else Zweig verwenden) oder möglich, wenn nicht ausdrücklich die letzten Parameter auf den gewünschten Typen umwandeln:

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

Verwandte Frage: Type error in ternary operator in Eigen

+0

Sie könnten auch '(...). Eval()', um die Auswertung der Ausdruck Vorlage zu erzwingen. –