2010-06-21 489 views
2

我遇到了一些“undefined reference to”错误的问题。我未必能够发布的代码,但该声明和我打电话的功能方式如下:实例化C++模板函数

声明:

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(标准::双端队列> &,INT,INT, 双,整型,短&,长)

未定义参考`诠释 pitch_detect(std :: deque> &,int,int)'

任何帮助解码上述错误是最受欢迎的。 谢谢, Sriram

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

回答

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

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

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

+0

啊!是。这是问题所在。我没有明确实例化模板。我是新来的模板,并有很多东西可以学习。问题解决了!谢谢大卫! – Sriram 2010-06-21 09:01:40

+0

你真的需要使用显式实例吗?在大多数情况下,最好是在头文件中提供模板的定义,并让编译器在使用时隐式地实例化它。 – 2010-06-21 17:20:20

2

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

1

我还没有尝试g ++,但你有没有尝试明确命名的类型?

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

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

+0

我没有明确实例化模板函数。这是问题所在。谢谢斯科特! – Sriram 2010-06-21 09:04:49