1

重複の可能性:
C++ テンプレート、未定義の参照

単純な配列からベクトルを構築する 3 つのファイルで構成される非常に単純なプログラムがあります。

//create.hpp

#ifndef CREATE_HPP_
#define CREATE_HPP_

#include <vector>

using namespace std;

template<class T>
vector<T> create_list(T uarray[], size_t size);

#endif /* CREATE_HPP_ */

//create.cpp

#include "create.hpp"

template<class T>
vector<T> create_list(T uarray[], size_t size){
    vector<T> ulist(uarray, uarray + size);
    return ulist;
}

//main.cpp

#include <vector>
#include <iostream>

#include "create.hpp"

using namespace std;


int main(){
    char temp[] = { '/', '>' };
    vector<char> uvec = create_list<char>(temp, 2);

    vector<char>::iterator iter=uvec.begin();
    for(;iter != uvec.end();iter++){
        cout<<*iter<<endl;
    }

    return 0;
}

ビルドプロセスは次のとおりです。

g++ -O0 -g3 -Wall -c -fmessage-length=0 -o create.o create.cpp
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o main.o main.cpp
g++ -o main.exe main.o create.o

プログラムのビルド中に、次のエラーが発生します。

main.o: In function `main':
../main.cpp:18: undefined reference to `std::vector<char, std::allocator<char> > create_list<char>(char*, unsigned int)'

このプログラムは実にシンプルです。ただし、コンパイルは成功しましたが、リンクは失敗しました。次に、すべてのコードを 1 つのファイルに移動すると、すべてが魅力的に機能します。誰でもこれを理解するのを手伝ってもらえますか?

4

2 に答える 2

6

はい。答えは複雑です。これは、テンプレートが C++ で実際にどのように機能するかに関係しています。

簡単な答え: 完全なテンプレート定義がヘッダー ファイルに含まれているか、明示的なインスタンス化が必要です (例: http://msdn.microsoft.com/en-us/library/by56e477(v=vs.80).aspx ) CPP ファイル内の特定のタイプに対して。

長い答え (理由): テンプレートは、バイナリ (オブジェクト) にコンパイルできるコードではありません。それらは単なる「コードを作成するためのレシピ」であり、コードはインスタンス化のプロセスでのみ作成できます。これは、テンプレートを不正確に使用すると、コンパイル時間が長くなり、必要なバイナリよりも大きくなる可能性がある理由でもあります。

于 2012-12-22T17:44:34.887 に答える
4

テンプレートを別の.cppファイルで定義しました。各ファイルは個別にコンパイルされます。実行create.cpp中のコードが含まれていないため、コンパイラによって破棄されています。その後、リンク段階で、リンカーが のバイナリをmain.cppとリンクしようとするcreate_listと、他のコンパイル済みオブジェクトでそれを見つけることができないため、このエラーが発生します。それを解決するには、テンプレートを少なくとも 1 回インスタンス化するcreate.cppか、ヘッダー ファイル内に実装する必要があります。

于 2012-12-22T17:48:54.120 に答える