feelfree
feelfree

Reputation: 11763

C++ class follows with template keyword

I am compiling a C++ library that use a C++ mathematics library Eigen3. However, the following codes introduce some syntax errors when compiling with VC2013:

template <typename Derived>
    inline Eigen::Transform<typename Derived::Scalar, 3, Eigen::Isometry> v2t(const Eigen::MatrixBase<Derived>& x_) {
    Eigen::Transform<typename Derived::Scalar, 3, Eigen::Isometry> X;
    Eigen::Matrix<typename Derived::Scalar, 6, 1> x(x_);
    X.template linear() = quat2mat(x.template block<3,1>(3,0));
    X.template translation() = x.template block<3,1>(0,0);
    return X;
  }

The error messages are as follows:

Error   C2059   syntax error : 'template'    
Error   C2039   'X' : is not a member of 'Eigen::Transform<float,3,1,0>'        
Error   C2059   syntax error : 'template'    
Error   C2039   'X' : is not a member of 'Eigen::Transform<float,3,1,0>'    

I have never saw codes like that X.template so I have no idea how I can do to correct this compilation error. Any ideas?

Upvotes: 3

Views: 369

Answers (1)

Holt
Holt

Reputation: 37626

The template keyword should be used here to disambiguate between a template and a comparison operator, e.g.:

struct X {
    template <int A>
    void f();
};

template <class T>
void g() {
    T t{};
    t.f<4>(); // Error - Do you want to compare t.f with 4 
              // or do you want to call the template t.f ?
}

Here you need t.template f<4>() to "disambiguate". The issue with the library you used is that Eigen::Transform<...>::linear is not a template member function, so the template keyword is not necessary here, and should not be used (I think).

[temps.name#5]

A name prefixed by the keyword template shall be a template-id or the name shall refer to a class template. [ Note: The keyword template may not be applied to non-template members of class templates. —end note ] [...]

MSVC is right, Eigen::Transform<...>::linear is a non-template member of a class template, so the template keyword should not be applied. The following example from the standard should be ill-formed but compiles perfectly well with gcc and clang:

template <class T> struct A {
    void f(int);
    template <class U> void f(U);
};

template <class T> void f(T t) {
    A<T> a;
    a.template f<>(t); // OK: calls template
    a.template f(t); // error: not a template-id
}

There is already an open issue about this regarding the library you use on github, but without any answers from the author... Your could update the header (ncip/bm_se3.h) yourself or fork the project and make a pull-request on github.

Upvotes: 3

Related Questions