0

かなり長い間、テンプレート化された関数の実装を定義から分離するという古いas-c++の問題に苦労しています。C ++ 0x'externはこれに対する解決策のようですが、私はそれを適切に適用できません

私のコード:

main.cpp

#include <iostream>
#include <string>

#include "lexer.h"

int main(int argc, char const *argv[]) {
    std::string foo("foo");
    new lexer((foo.begin()),(foo.end()));
    return 0;
}

lexer.h

#ifndef lexer_h
#define lexer_h
class lexer {
    public:
    extern template<class InputIterator>
    lexer(InputIterator i, InputIterator end);
};
#endif //lexer_h

lexer.cpp

#include "lexer.h"
template<class InputIterator >
lexer::lexer(InputIterator i, InputIterator end) {
    //make it work
};

でコンパイルしg++ main.cpp lexer.cpp -std=c++0xます。後でオブジェクトファイルを使用したい。

では、どのように修正されたように見えますか?

4

2 に答える 2

1

の引数として使用される型の完全なセットを知らない限りInputIterator、定義はヘッダーファイルに入れる必要があります。

テンプレート定義(実装)は、必要なインスタンス化(引数)の完全なセットがわかっている場合にのみ、宣言から分離できます。.cppコンパイラーは、あるインスタンス化(変換単位)で使用されたインスタンス化を記憶できず、別のコードを使用してそれらを提供できません.cpp

Andyが言及しているように、あなたが探していると思われる動作は、以前はC ++ 03exportキーワードに割り当てられていましたが、これはほとんど実装されておらず、期待よりも役に立たないことが判明し、現在は標準から完全に削除されています。

このルートを使用したい場合(私は今、同様のライブラリを作成しています!)、externキーワードはclass {}スコープ外に移動する必要があり、.cppファイルは必要な特殊化を明示的にインスタンス化する必要があります。

// header file

class lexer {
    public:
    template<class InputIterator>
    lexer(InputIterator i, InputIterator end);
};

extern template lexer::lexer( foo::iterator, foo::iterator );
extern template lexer::lexer( bar::iterator, bar::iterator );

// source file

template<class InputIterator >
lexer::lexer(InputIterator i, InputIterator end) {
    //make it work
};

template lexer::lexer( foo::iterator, foo::iterator );
template lexer::lexer( bar::iterator, bar::iterator );
于 2013-02-21T16:50:32.747 に答える
0

それが機能しない理由は、クラステンプレートをインスタンス化しておらず、クラステンプレートのコンストラクターもインスタンス化していないためです。.cppそれ以外の変換ユニット(つまりファイル)を処理している間lexer.cpp、コンパイラーはそのコンストラクターを呼び出すことができません。その定義を参照してください。そのため、オブジェクトコードは出力されません。一方、その定義()を表示できるlexer.cpp唯一の変換ユニットでは、コンストラクターを呼び出さないため、コンパイラーはオブジェクトコードを出力しません。

その結果、コンストラクターのオブジェクトコードは、プログラムのコンパイル済み変換ユニットに存在せず、リンカーは、実行可能ファイルを作成しようとしたときに、クラスのコンストラクターへの未解決の参照について文句を言います。

externキーワードは、テンプレートが別の翻訳単位で(明示的に)インスタンス化されることがわかっている場合に、ある翻訳単位でのテンプレートのインスタンス化を防ぐために使用されます。これにより、コンパイル時間を節約できます。説明については、 StackOverflowに関するこのQ&Aを参照してください。

C++11規格のパラグラフ14.7.2/2から:

明示的なインスタンス化の構文は次のとおりです。

明示的インスタンス化:extern(opt)テンプレート宣言

明示的なインスタンス化には、明示的なインスタンス化の定義と明示的なインスタンス化の宣言の2つの形式があります。明示的なインスタンス化宣言externは、キーワードで始まります。

したがって、提供しているのは単なる宣言です。リンカから未解決の参照エラーを取得せずに、ファイル内のクラステンプレートのメンバー関数定義を委任する方法はありません.cpp。ただし、同じ変換ユニット(唯一のこれらの定義にアクセスできます)。

C ++ 03には、export達成しようとしていることを実行できるというキーワードがありましたが、コンパイラベンダーにとって実装が難しすぎることが判明したため、C++11の標準化中に削除されました。

于 2013-02-21T16:36:18.067 に答える