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 に答える