实例化C ++模板函数

时间:2010-06-21 08:40:01

标签: stl g++ deque undefined-reference

我面临一些“未定义引用”错误的问题。我可能无法发布代码,但声明和我调用函数的方式如下:

声明:

template <typename T>
int pitch_detect(deque<T>& x, int offset, int len);

template <typename T>
int is_voiced(
  deque<T>& x, int offset, int len,
  double avg_energy, int pre_voice,
  short& s_flag,
  long nsamples
);

我调用上述函数如下:

x = is_voiced(superFrame_, cur_offset_, f_len_,
    avgEnergy_, frame_voicing_[1], silence_flag_, nsamples_);

y = pitch_detect(superFrame_, cur_offset_, f_len_);

以上语句(我调用函数的地方)被标记为错误。这些是消息:

  

对int的未定义引用   is_voiced(std :: deque&gt;&amp;,int,int,   double,int,short&amp;,long)

     

对int的未定义引用   pitch_detect(std :: deque&gt;&amp;,int,int)'

非常欢迎任何解码上述错误的帮助。 谢谢, 斯利拉姆

编辑: 上述函数在单独的头文件和相应的C ++文件中定义。当我尝试编译它们并创建一个目标文件时,我没有遇到任何问题。这些错误可在链接器阶段看到。

3 个答案:

答案 0 :(得分:3)

您是否为这些模板提供了定义?您是自己显式实例化模板还是允许编译器实例化它们?

如果你提供了一个模板声明,但编译器没有在同一个翻译单元中看到定义,它会假设模板将在另一个翻译单元中实例化,并且只会生成调用,但不会编译(不会看到它不可能做的定义)特定的实例化。稍后在链接时链接器将看到调用,但不会看到实例化,并且会因未定义的引用错误而失败。

最简单的解决方案就是将模板声明和定义放在一起:

template <typename T>
int is_voiced( deque<T>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples ) 
{
  // code here
}

然后当你使用is_voiced(...)时,编译器会隐式为你实例化模板(它会看到代码,然后编译它)。

在某些情况下,您不希望编译器隐式实例化您的模板(您知道将使用哪些类型,并且您不希望编译器允许其他用途 - 或者编译成本很高并希望通过仅在单个翻译单元中实例化模板来加速编译。对于这些情况,您需要在翻译单元中提供您自己的显式实例化。

// header
template <typename T>
int is_voiced( deque<T>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples ); 

// cpp
template <typename T>
int is_voiced( deque<T>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples ) {
   // code goes here
}
// explicit instantiation for int
template int is_voiced( deque<int>& x, int offset, int len, double avg_energy, int pre_voice, short& s_flag, long nsamples );

然后编译该实现文件并将其与项目的其余部分链接。

注意:建议在头文件中提供完整的模板定义,以便编译器可以隐式实例化它,除非你有充分的理由不这样做。

答案 1 :(得分:2)

将函数的定义放在头文件中,而不是放在单独的CPP文件中;并且,在头文件中,使用inline关键字为函数定义添加前缀,以避免链接器抱怨重复定义。

答案 2 :(得分:1)

我没有尝试过g ++,但您是否尝试过明确命名类型?

x = is_voiced<PutTypeNameHere>(superFrame_, etc);

定义和调用是否来自同一个dll / exe?如果没有,您可能需要使用您调用它们的类型显式实例化模板函数。

相关问题