使用带有std :: vector和本征矩阵的模板,来自GCC的未定义参考错误? [英] Undefined reference error from GCC using a template with a std::vector and an Eigen Matrix?

查看:46
本文介绍了使用带有std :: vector和本征矩阵的模板,来自GCC的未定义参考错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用GCC编译以下代码时,我遇到未定义的引用错误通过以下命令在x86_64-suse-linux下使用4.7.2 20130108:

  g ++ main.cpp func.cpp -I/path/to/eigenlibrary/eigen_3.2.1 

错误消息显示为:

  main.cpp :(.text + 0x1d):对`void f< 2>(std :: vector< Eigen :: Matrix< double,2,2,((Eigen :: ._ 84)0)|(((((2)==(1))&&(((2)!=(1))))?((Eigen :: ._ 84)1):(((((2)==(1))&&(((2)!=(1))))?(((Eigen :: ._ 84)0):((Eigen :: ._ 84)0))),2,2>,std :: allocator< Eigen :: Matrix< double,2,2,(((Eigen :: ._ 84)0)|(((((2)==(1))&(((2)!=(1)))?((Eigen :: ._ 84)1):(((((2)==(1))&&(((2)!=(1))))?(((Eigen :: ._ 84)0):((Eigen :: ._ 84)0))),2,2>>>&)' 

请注意,这与模板实现与头文件分开的事实无关,因为没有模板函数的(通用)实现,而只是模板特化.模板特化的实现不能放入头文件中,因为这会产生多个定义错误.

这里另一个奇怪的事情是,如果我更改main.cpp中的前两个头文件包含项的顺序(本征/密集和向量),则不会发生错误.我对此一无所知,除仅更改标头包含的顺序然后"之外的任何帮助将不胜感激.

main.cpp:

  #include< vector>#include< Eigen/Dense>//一旦更改标题包含的顺序,就不会发生错误,如下所示://#include< Eigen/Dense>//#include< vector>#include"func.h"int main(){std :: vector< Eigen :: Matrix< double,2,2>>m;f 2(m); m 2(m).} 

func.h

  #ifndef FUNC_H#定义FUNC_H#include< Eigen/Dense>#include< vector>模板< int N>无效f(std :: vector< Eigen :: Matrix< double,N,N>& m));模板<>无效f 2(std :: vector Eigen :: Matrix & m);#万一 

func.cpp

  #include"func.h"#include< vector>模板<>无效f 2(std :: vector  

解决方案

我知道这是一个老问题,但是我们在不同的环境中遇到了相同的问题,我想我会分享我们的解决方案./p>

至少在GCC 4.8.2-19ubuntu1中,针对未解决的链接错误的解决方案是在func.h中替换以下内容

 模板< int N>无效f(std :: vector< Eigen :: Matrix< double,N,N>& m)); 

使用

 模板< int N>无效f(std :: vector< Eigen :: Matrix< double,N,N,0>>& m); 

请注意,第四个模板参数显式指定为0,这是链接器错误中模板函数声明中显示的表达式的结果,

 (((Eigen :: ._ 84)0)|(((((2)==(1))&&(((2)!=(1))))?((Eigen :: ._ 84)1):(((((2)==(1))&&(((2)!=(1))))?(((Eigen :: ._ 84)0) 

该表达式来自第四个模板参数的默认值,该默认值在Eigen ForwardDeclarations.h 文件中以

的形式给出

 自动对齐|((_Rows == 1&&__ Cols!= 1)?:(_ Cols == 1&&__ Rows!= 1)?上校:EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION) 

有另一种方法可以解决本征代码中的问题,我将在稍后介绍.

问题的原因似乎是GCC编译器延迟了对该表达式的求值,并且该表达式涉及匿名枚举类型,其类型名称在表达式中明确给出((Eigen :: ._ 84)).此外,GCC编译器似乎使用计数器生成匿名 enum 类型名称,因此,类型名称取决于之前已经出现过多少个匿名 enum 类型,但对于不同的编译单元.这就是为什么在包含 Eigen/Dense 之前添加 #include< vector> 或匿名 enum 定义会触发此问题的原因.编译后的 f< 2> 中的类型名称很可能是(Eigen :: ._ 83),因此不匹配.

恐怕我不是编译器内部或C ++标准深度的专家,也不能说这是GCC编译器中的错误还是仅仅是解释上的差异.

另一种涉及修改本征代码并且似乎可行的解决方案是在 Constants.h 中为 enum 提供一个名称,该名称定义 AutoAlign RowMajor ColMajor ,因为问题在于使用匿名 enum 类型.例如:

 /** \ ingroup枚举*包含\ p _Options模板参数的可能值的枚举*矩阵,数组和BandMatrix.*/列举MatrixOptionsType {ColMajor = 0,RowMajor = 0x1,自动对齐= 0,DontAlign = 0x2}; 

我不确定Eigen开发人员是否可以接受.

I am experiencing an undefined reference error, when compiling the following code using GCC 4.7.2 20130108 under x86_64-suse-linux via the command:

g++ main.cpp func.cpp -I/path/to/eigenlibrary/eigen_3.2.1

The error message reads:

     main.cpp:(.text+0x1d): undefined reference to `void f<2>(std::vector<Eigen::Matrix<double, 2, 2, 
((Eigen::._84)0)|((((2)==(1))&&((2)!=(1)))?
    ((Eigen::._84)1) : ((((2)==(1))&&((2)!=(1)))?((Eigen::._84)0) : ((Eigen::._84)0))), 2, 2>,
     std::allocator<Eigen::Matrix<double, 2, 2, ((Eigen::._84)0)|((((2)==(1))&&((2)!=(1)))?
    ((Eigen::._84)1) : ((((2)==(1))&&((2)!=(1)))?((Eigen::._84)0) : ((Eigen::._84)0))), 2, 2> > >&)'

Please note that this has nothing to do with the fact that the template implementation is separated from the header file, because there is no (generic) implementation of the template function, but only a template specialization. The implementation of the template specialization can not be put into the header file, because this yields multiple definition errors.

Another strange thing here is that if I change the order of the first two header inclusions in main.cpp (Eigen/Dense and vector) the error does not occur. I have no understanding for this and any help that goes beyond 'simply change the order of the header inclusions then' would be highly appreciated.

main.cpp:

#include <vector>
#include <Eigen/Dense>

//error does not occur once I change order of header inclusion like so:
//#include <Eigen/Dense>
//#include <vector>

#include "func.h"

int main() {
    std::vector<Eigen::Matrix<double, 2, 2> > m;  
    f<2>(m);
}

func.h

#ifndef FUNC_H
#define FUNC_H

#include <Eigen/Dense>
#include <vector>

template <int N>
void f(std::vector<Eigen::Matrix<double, N, N> >& m);

template <> void f<2>(std::vector<Eigen::Matrix<double, 2, 2> >& m);

#endif 

func.cpp

#include "func.h"
#include <vector>

template <>
void f<2>(std::vector<Eigen::Matrix<double, 2, 2> >& m) {} 

解决方案

I know that this is an old question, but we've run into the same problem in a different context, and I thought I would share our solution.

A solution to the unresolved link error, at least for GCC 4.8.2-19ubuntu1, is to replace the following in func.h

template <int N>
void f(std::vector<Eigen::Matrix<double, N, N> >& m);

with

template <int N>
void f(std::vector<Eigen::Matrix<double, N, N, 0> >& m);

Note that the forth template argument is explicitly given as 0, which is the result of the expression shown in the template function declaration in the linker error,

((Eigen::._84)0)|((((2)==(1))&&((2)!=(1)))?
    ((Eigen::._84)1) : ((((2)==(1))&&((2)!=(1)))?((Eigen::._84)0)

The expression comes from the default value for the forth template parameter, which is given in the Eigen ForwardDeclarations.h file as

AutoAlign |
( (_Rows==1 && _Cols!=1) ? RowMajor
: (_Cols==1 && _Rows!=1) ? ColMajor
: EIGEN_DEFAULT_MATRIX_STORAGE_ORDER_OPTION )

There is another way to fix the problem in the Eigen code, which I'll mention in a minute.

The cause of the problem seems to be that the GCC compiler delays the evaluation of this expression and that the expression involves anonymous enum types whose type names are explicitly given in the expression ((Eigen::._84) in this case). Further, the GCC compiler appears to generate anonymous enum type names using a counter, and therefore the type name depends on how many anonymous enum types have appeared before, which can vary for different compilation units. This is why adding #include <vector> or an anonymous enum definition before including Eigen/Dense triggers the problem. The type name in the compiled f<2> is likely (Eigen::._83), and thus the mismatch.

I'm afraid that I'm not an expert on the internals of compilers or the depths of the C++ standard, and can't say if this a bug in the GCC compiler or simply a matter of a difference of interpretation.

Another solution that involves modifying the Eigen code and seems to work is to provide a name for the enum in Constants.h that defines AutoAlign, RowMajor, and ColMajor, as the issue is in using anonymous enum types. For example:

/** \ingroup enums
  * Enum containing possible values for the \p _Options template parameter of
  * Matrix, Array and BandMatrix. */
enum MatrixOptionsType {
  ColMajor = 0,
  RowMajor = 0x1,
  AutoAlign = 0,
  DontAlign = 0x2
};

I'm not sure if that would be acceptable to the Eigen developers, though.

这篇关于使用带有std :: vector和本征矩阵的模板,来自GCC的未定义参考错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆