Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio 2010 doesn't like typedef typename in mixin

I have some code that compiles fine with gcc but Visual Studio does not like. I have distilled it to a minimal example below:

#include "stdafx.h"

#include <Eigen/Dense>

template<class Base>
class Timestamp : public Base
{
public:
    typedef typename Base::PointType PointType;
    double timestamp;
};

/*
struct Point {};

struct PointXYZ : public Point
{
    typedef PointXYZ PointType;
};
*/

struct PointXYZ : public Eigen::Vector3d
{
    typedef PointXYZ PointType;
};

int _tmain(int argc, _TCHAR* argv[])
{
    Timestamp<PointXYZ> point;
    return 0;
}

The error is "error C2039: 'PointType' : is not a member of 'Eigen::PlainObjectBase<Derived>'"

The class PlainObjectBase is part of the Eigen library. If I replace the definition of PointXYZ with the one in comments that derives from an empty "Point" class, it compiles fine in VS as well. Any suggestions on why this is happening and what can be changed for VS to accept it as gcc does?

like image 481
David Doria Avatar asked Dec 15 '25 19:12

David Doria


1 Answers

Is there a reason why you're redefining the type member PointType in Timestamp? You're already inheriting from a type that you expect to contain the PointType type member, which means that Timestamp has the PointType type member as well via inheritence. If you get rid of this typedef from Timestamp, you shouldn't have this problem.

I'm not familiar with Eigen, but I imagine it's this library. If so, the documentation shows that Vector3d is a typedef for Matrix (i.e. a Vector3d is just a Matrix), which itself contains a typedef named Base representing the base class PlainObjectBase<Matrix>:

typedef PlainObjectBase<Matrix> Base;

My guess is that when you do:

typedef typename Base::PointType PointType;

the Base is being evaluated as the Matrix' Base typedef and not the template type parameter Base, so it's effectively trying to do what your error message says:

typedef typename PlainObjectBase<Derived>::PointType PointType;

Which obviously fails because PlainObjectBase doesn't contain a PointType type member, not to mention that this isn't what you're trying to do.

Does changing the template type parameter for Timestamp to B for example resolve things?

template<class B>
class Timestamp : public B
{
public:
    typedef typename B::PointType PointType;
    double timestamp;
};

That would confirm that this is the problem, and presumably indeed a bug in Visual Studio 2010 (try later versions if you can). Personally though I would recommend simply removing the typedef, since you're already inheriting it.

like image 191
Jorge Israel Peña Avatar answered Dec 17 '25 07:12

Jorge Israel Peña



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!