2009-03-16 19 views
28

私が機能を持っているので同じように宣言:C++テンプレート、未定義の参照

template <typename T> 
T read(); 

などのように定義された:

template <typename T> 
T packetreader::read() { 
    offset += sizeof(T); 
    return *(T*)(buf+offset-sizeof(T)); 
} 

しかし、私は私のmain()関数でそれを使用しようとすると:

packetreader reader; 
reader.read<int>(); 

は私がg ++から次のエラーを取得する:

g++ -o main main.o packet.o 
main.o: In function `main': 
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()' 
collect2: ld returned 1 exit status 
make: *** [main] Error 1 

誰でも正しい方向に向けることができますか?

+0

可能重複テンプレート関数を宣言し、実装されている一般的な方法を知っているように、文字列(GCC)で使用される場合、テンプレートとして機能するように未定義の参照](HTTP:// stackoverflowの。com/questions/614233/undefined-function-template-with-string-gccの使用時) – outis

答えて

24

キーワードexportを使用する必要があります。しかし、私はG ++には適切なサポートがないと思うので、ヘッダーにテンプレート関数の定義を含めて、翻訳単位で使用できるようにする必要があります。これは、テンプレートの<int> 'バージョン'が作成されていないため、<typename T> 'バージョンのみ'です。

簡単な方法は、#include .cppファイルです。しかし、これは問題を引き起こす可能性があります。他の機能が.cppファイル内にある場合また、コンパイル時間も増加する可能性があります。

テンプレート関数を独自の.cppファイルに移動し、ヘッダーにまたはというキーワードを含めて別々にコンパイルします。

More information on why you should try and put template function definitions in its header file (and ignore export altogether).

+0

packet.cppコードをpacket.hに移動して名前を変更することをお勧めしますか?私はしばしばブーストで使用されてきたように "packet.hpp"のような何か? –

+1

@ダニエル、すべての関数がテンプレート関数である場合のみ。そうしないと、関数の一部を移動して.cppファイルを保持することができなくなります。 – strager

4

テンプレート関数とベストプラクティスは、ヘッダファイルでそれらを定義することです。それらはコンパイル時に作成されるので、コンパイラはそのように定義する必要があります。

テンプレートの場合はexportがよりサポートされるようになると、これは当てはまりませんが、今はまだほとんど使用できません。

+0

'export'の使用はお勧めしません。 http://www.parashift.com/c++-faq-lite/templates.html#faq-35.14によると、C++ 0x標準から投票されました。 – uckelman

12

問題は、関数テンプレートは関数ではないということです。必要に応じて関数を作成するためのテンプレートです。

テンプレートが機能するためには、コンパイラに直観的に2つの情報が必要です。テンプレート自体と、それに代入する必要のあるタイプです。 これは関数呼び出しとは異なり、コンパイラは関数が存在することを知るとすぐに生成することができます。関数が何をしているかを知る必要はありません。ちょうどvoid Frobnicate(int, float)のように見えます。

関数テンプレートを定義せずに宣言すると、そのようなテンプレートは存在するものの、その外観は表示されません。コンパイラがインスタンス化できるだけでは十分ではありません。完全な定義も見ることができなければなりません。通常の解決策は、テンプレート全体を必要な場所に含めることができるヘッダーに置くことです。

0

これらのコンパイラサポートテンプレートは別々のコンパイルファイルですか?

Iは、ヘッダファイルでの

+0

コモウは私が信じています。そして現代版のMSVC *かもしれませんが、私は自分でそれをチェックしていません。 – vava

+0

最新のVS2008はまだエクスポートキーワードをサポートしていません。 MSの皆さんが将来のサポートのためにこのキーワードを予約しているようです:warning C4237: 'export'キーワードはまだサポートされていませんが、将来の使用のために予約されています –