2

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

声明:

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 >&, int, int, double, int, short&, long) 的未定义引用

对“int pitch_detect(std::deque >&, int, int)”的未定义引用

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

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

4

3 回答 3

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 );

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

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

于 2010-06-21T08:47:08.963 回答
2

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

于 2010-06-21T08:46:16.737 回答
1

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

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

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

于 2010-06-21T08:46:55.393 回答