• ベストアンサー

コンパイルエラー: LNK2001

今、ベクトル計算を簡単にするクラスを作ってみようとしています。 //vector3.h template<class TT> class vector3{ public:   enum{NUM=3};   TT x[NUM];   void set(const TT *vv)void set(const TT *vv){     int i;     for(i=0;i<NUM;i++){       x[i]=vv[i];     }   } }; のように、set関数をクラスの中に書いていると問題無いのですが、以下のように、 //vector3.h template<class TT> class vector3{ public:   enum{NUM=3};   TT x[NUM];   void set(const TT *vv); }; //test.cpp #include"vector3.h" template<class TT> void vector3<TT>::set(const TT *vv){   int i;   for(i=0;i<NUM;i++){     x[i]=vv[i];   } } と、cppファイルの中に書き換えると以下のようにエラーが出るようになります。 error LNK2001: 外部シンボル ""public: void __thiscall vector3<double>::set(double const *)" (?set@?$vector3@N@@QAEXPBN@Z)" は未解決です。 fatal error LNK1120: 外部参照 1 が未解決です。 これはいったい何故なのでしょうか? 使用しているのはVisualC++2008ExpressEditionです 宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

コンパイル時、test.cpp で実装されたメンバ・テンプレートの テンプレート引数 TT の具体的な型が不明なのでコンパイルしようが ありません。コンパイルされませんからリンク時にも見つかりません。

glarelance
質問者

お礼

解答有り難うございます。 一つ疑問に思ったのですが、includeはファイルを引っ付けるだけって言う認識なのですが、templateの有効範囲はincludeとか関係なく、単一のファイルのみの有効範囲ということになっているのでしょうか? また、templateは、「template<class T>」と書いた後の一番最初の関数もしくは、classの「{}」の範囲のみで有効と言うことでしょうか? templateの名前空間の有効範囲がよく分からないので宜しくお願いします。

その他の回答 (2)

回答No.3

> includeはファイルを引っ付けるだけって言う認識なのですが、 その通りです。 > templateの有効範囲はincludeとか関係なく、 > 単一のファイルのみの有効範囲ということになっているのでしょうか? 有効範囲とは何のことを言っていますか? 「どこから使える(呼べる)か」ということなら、どこからでも使えます。 質問にあったコードが良い例になっています。 コンパイルエラーにはなっていませんね。 vector3<double>を使うのに問題はなく、 vector<double>の「実体が存在しない」ため リンク・エラーになっています。

glarelance
質問者

お礼

分かりました。とりあえず、今回教えて貰ったことを参考に色々弄くってみます。 どうも有り難うございました。

回答No.1

 こんにちは。  メンバ関数の中身もヘッダに置くか、test.cppをインクルードするかしないと無理なのではないでしょうか。  http://ja.wikipedia.org/wiki/C%2B%2B  exportと言うキーワードが在るのですが、VC2008でも使えなかったような気がします。  後、vector3が継承しておらず、コンストラクタ系を書いていなければ、  vector3<int> v = {0,1,2};  と言った具合で、固定配列の初期化と同じ書き方が出来ると思います。  更にネタとして、  template<class TT, int NUM> class vector3{  public:   TT x[NUM];   void set(const TT *vv);  };  と書いて、  vector3<int, 3> v = {0,1,2};  と言った書き方も出来ます。

glarelance
質問者

お礼

解答有り難うございます。 色々調べ回った結果、テンプレートの明示的なインスタンスの生成てことをやっておくとうまくいくらしいですね。 http://www.fides.dti.ne.jp/~oka-t/cpplab-template-3.html まあ、それ以前に良く考えれば、テンプレートはコンパイル時に処理される静的なものなのだから、ファイル分割何かしたらテンプレートが定義されていなくなるのだから、コンパイルできなくて当然ですよね。 >>template<class TT, int NUM> テンプレートって値も指定できるんですね。全然知りませんでした^^; あと、このクラスは typedef vector3<double> vector3d; みたいな感じで定義して使おうかなって考えてます。 どうも有り難うございました。

関連するQ&A