I have this class:
template < unsigned N, typename T >
class MY_EXPORT my_point : protected Eigen::Matrix< T, N, 1 >
{
public:
using vector_type = Eigen::Matrix< T, N, 1 >;
my_point() : vector_type{ vector_type::Zero() } {}
using vector_type::vector_type;
};
My Linux (GCC) build is fine. However, on Windows (MSVC 15.9.16), I get really strange errors:
c:\include\eigen3\eigen\src\core\densebase.h(482): error C2338: THIS_METHOD_IS_ONLY_FOR_1x1_EXPRESSIONS (compiling source file c:\code\my_point.cxx) [C:\workspace\KwiverWindows\build\vital\vital.vcxproj]
c:\include\eigen3\eigen\src\core\densebase.h(481): note: while compiling class template member function 'const float &Eigen::DenseBase<Derived>::value(void) const'
with
[
Derived=Eigen::Matrix<float,4,1,0,4,1>
] (compiling source file c:\code\my_point.cxx)
c:\include\eigen3\eigen\src\core\matrixbase.h(50): note: see reference to class template instantiation 'Eigen::DenseBase<Derived>' being compiled
with
[
Derived=Eigen::Matrix<float,4,1,0,4,1>
] (compiling source file c:\code\my_point.cxx)
c:\include\eigen3\eigen\src\core\plainobjectbase.h(100): note: see reference to class template instantiation 'Eigen::MatrixBase<Derived>' being compiled
with
[
Derived=Eigen::Matrix<float,4,1,0,4,1>
] (compiling source file c:\code\my_point.cxx)
c:\include\eigen3\eigen\src\core\matrix.h(180): note: see reference to class template instantiation 'Eigen::PlainObjectBase<Eigen::Matrix<float,4,1,0,4,1>>' being compiled (compiling source file c:\code\my_point.cxx)
It looks like the compiler is trying to instantiate inappropriate methods (e.g. a later error is trying to instantiate w()
for a 3-vector). What am I doing wrong? (Why is this not a problem when using Eigen::Matrix
directly?)
Here is a live demo.
The problem is that Eigen doesn't use SFINAE/enable_if
to hide "inappropriate" members, it just relies on them never being instantiated (with static assertions if someone tries to use them). As a result, an Eigen
class — at least, Eigen::Matrix
— cannot be explicitly instantiated.
This can be seen with a trivial example:
#include <Eigen/Core>
template class Eigen::Matrix< double, 3, 1 >;
The real mystery is why GCC allows explicit instantiations of classes derived from Eigen::Matrix
. MSVC does not, but it seems that MSVC is probably in the right, here.
The short term solution is to not export my_point
. This requires, of course, that the definitions of all of my_point
's methods are either visible in the header, or are individually exported (rather than trying to export the whole class).
The longer term solution would be to fix Eigen so that its types can be explicitly instantiated: https://eigen.tuxfamily.org/bz/show_bug.cgi?id=1768.