GCC undefined reference link error caused by anonymous enum values in default Matrix template options argument
Submitted by D Kessler
Assigned to Nobody
Link to original bugzilla bug (#1213)
Version: 3.2
Description
Created attachment 701
Source and Makefile demonstrating linker error using GCC 4.8.2
Not sure if this is a bug in GCC or a difference in interpretation of the C++ standard, but we've run into a tricky link error when using the Eigen Matrix class in a templated function defined in a library that is used by another library. The attached code demonstrates the problem, which occurs with GCC 4.2.8 on an Ubuntu Linux system, although it appears to be the same problem as discussed on http://stackoverflow.com/questions/24730981/undefined-reference-error-from-gcc-using-a-template-with-a-stdvector-and-an-ei
The specific error, for the attached example, is:
./libitest.a(testilib.o): In function TriangulateIt(std::vector<Eigen::Matrix<float, 3, 1, 0, 3, 1>, std::allocator<Eigen::Matrix<float, 3, 1, 0, 3, 1> > > const&)': testilib.cpp:(.text+0x14): undefined reference to
bool TriangulatePolygon<float, 3>(std::vector<Eigen::Matrix<float, 3, 1, ((Eigen::._86)0)|((((3)==(1))&&((1)!=(1)))?((Eigen::._86)1) : ((((1)==(1))&&((3)!=(1)))?((Eigen::._86)0) : ((Eigen::._86)0))), 3, 1>, std::allocator<Eigen::Matrix<float, 3, 1, ((Eigen::._86)0)|((((3)==(1))&&((1)!=(1)))?((Eigen::._86)1) : ((((1)==(1))&&((3)!=(1)))?((Eigen::._86)0) : ((Eigen::._86)0))), 3, 1> > > const&)'
The issue seems to be the use of anonymous enum values in the expression defining the default value for the options parameter of the Matrix template, and that GCC is not fully evaluating the expression before storing the template function signature in a library. Further, the type name generated for anonymous enums ("Eigen::._86" in the error above) appears to use a counter, which can be different for different compilation units (in the example provided, the type name is different for the testlib and testilib libraries, where the function definition is in the testlib library and is being referenced by the testilib library).
One solution is to explicitly provide a value for the fourth, "options" template argument of the Matrix class, as in this example from the attached files:
#define VecDT_ Eigen::Matrix<T,dim,1,0>
Another solution that appears to work is to provide a name for the anonymous enum involved, defined in Constants.h. For example (adding "MatrixOptionsType"):
/** \ingroup enums
- Enum containing possible values for the \p _Options template parameter of
- Matrix, Array and BandMatrix. /
enum MatrixOptionsType {
/* Storage order is column major (see \ref TopicStorageOrders). /
ColMajor = 0,
/* Storage order is row major (see \ref TopicStorageOrders). /
RowMajor = 0x1, // it is only a coincidence that this is equal to RowMajorBit -- don't rely on that
/* Align the matrix itself if it is vectorizable fixed-size /
AutoAlign = 0,
/* Don't require alignment for the matrix itself (the array of coefficients, if dynamically allocated, may still be requested to be aligned) */ // FIXME --- clarify the situation
DontAlign = 0x2
};
I haven't worked with the interior of the Eigen code to know if this is a reasonable solution, or if the burden should be on the user of the Eigen library to avoid the GCC issue by explicitly giving a value for the Matrix options template parameter.
Note that a colleague has reported to me that the problem still occurs in Eigen 3.3beta1, but that it doesn't occur unless the code is compiled with the -march=native.
Attachment 701, "Source and Makefile demonstrating linker error using GCC 4.8.2":
template-link-eigen-bug.tgz