2

I have a class with an Eigen::Quaterniond as a protected member variable. I want to access it through the method attitude(). There are three ways I can think to do this right now, and none of them seem to work.

This is a minimum working example in a google test format.


#include "gtest/gtest.h"
#include <Eigen/Geometry>

class MyClass{
public:
    MyClass( double w, double x, double y, double z ) : attitude_(w,x,y,z) {}

    Eigen::Quaterniond&       attitude1()       { return attitude_; }
    const Eigen::Quaterniond& attitude1() const { return attitude_; }

    // compilation fails with " error: 'IsVectorAtCompileTime' is not a member of 'Eigen::Quaternion<double>' "
    // Eigen::Ref<Eigen::Quaterniond>             attitude2()       { return attitude_; }
    // const Eigen::Ref<const Eigen::Quaterniond> attitude2() const { return attitude_; }

    Eigen::Map<Eigen::Quaterniond>             attitude3()       { return Eigen::Map<Eigen::Quaterniond>(attitude_.coeffs().data()); }
    const Eigen::Map<const Eigen::Quaterniond> attitude3() const { return Eigen::Map<const Eigen::Quaterniond>(attitude_.coeffs().data()); }

protected:
    Eigen::Quaterniond attitude_;
};

TEST(QuaternionTest, const_reference ){

    MyClass a(0.2,0.3,0.4,0.5);
    const MyClass& b(a);

    {
        const double& pt1 = a.attitude1().w();
        const double& pt2 = b.attitude1().w();
        EXPECT_EQ(&pt1, &pt2); // FAILS
    }

    // {
    //     const double& pt1 = a.attitude2().w();
    //     const double& pt2 = b.attitude2().w();
    //     EXPECT_EQ(&pt1, &pt2);
    // }

    {
        const double& pt1 = a.attitude3().w();
        const double& pt2 = b.attitude3().w();
        EXPECT_EQ(&pt1, &pt2); // FAILS
    }
}

The commented method is the way I typically return references to internally stored Eigen objects, which enables me to then decide on the actual data storage internally without it being known past the interface (i.e stacking some Vector3 into a contiguous piece of memory).

The compile error looks like a bug to me, as we definitely do know the length of the Quaternion at compile time, it's really just a dressed up Vector4d.

Am I doing something obviously wrong?

  • is `EXPECT_EQ` taking pointers to doubles? You are passing pointers. – lakeweb Jan 28 '20 at 19:33
  • Yes, I am trying to check that the memory addresses for the data are the same. I am doing this by checking that the pointers are the same. – rhetorical5 Jan 28 '20 at 19:42
  • Are you using Microsoft's compiler? I see the same problem you do. And [first hit](https://stackoverflow.com/questions/1898524/difference-between-pointer-to-a-reference-and-reference-to-a-pointer) says `if( p == pr ) // true!` And, for sure, if i do it with pointers the comparison is true. Someone else may know more about this. Disassembly shows a return of addresses 4 bytes apart, fails. – lakeweb Jan 28 '20 at 21:11
  • And, I went back to take one more look. It got weirder.. The first block passes now. The second block won't pass because you are returning objects, not references. – lakeweb Jan 28 '20 at 21:41
  • I would add that as `attitude3` is returning a temporary, the double reference is not going to be valid. I'm surprised that the compiler didn't complain. – lakeweb Jan 28 '20 at 21:51

0 Answers0