templateのmap処理でエラー

このQ&Aのポイント
  • C++のTemplateを勉強中です。Parentクラス内でChildクラスを管理している際に、map処理でエラーが発生しています。具体的には、Parentクラス内でChildクラスのポインタとIDを保持するためにSTLのmapを使用していますが、m_Mapをstaticにするとエラーが発生します。エラーの詳細についても説明しています。
  • エラーの内容は、「undefined reference to `Parent<Child>::m_Map'」です。このエラーは、m_Mapをstaticにすると発生するものであり、Singletonとして動作させるためには一元管理するmapをstaticにしたいと述べています。
  • 対処方法としては、m_Mapをstaticにする理由やエラーを解消する方法についての質問をしています。具体的なコードやエラーメッセージを示していますので、詳しい方にお答えいただけることを求めています。
回答を見る
  • ベストアンサー

templateのmap処理でエラー

C++のTemplateを勉強中のものです。 以下の処理でエラーが発生します。(ソースは一番下です) コンパイラはgcc4.6.6です。 【やりたいこと】 ・Parentクラス内でChildクラスを管理したい ・ParentクラスはSingleton扱いにしたい  (※下のソースではシンプルにするためにあえて実装していません) ・Parent内でChildクラスのポインタとIDをSTLのmapを使って保持したい 【エラー内容】 ・発生箇所:m_Map.insertの行 ・エラー内容は「undefined reference to `Parent<Child>::m_Map'」 ・m_Mapをstaticにしなければ出ない  ※上記でも述べましたが、Singletonとして扱いたいので、一元管理するmapはstaticとしたいです。 で、質問なのですが ・staticの場合に出る理由 ・上記エラーの解消方法 です。 お詳しい方いましたらご教示いただけませんでしょうか? ========================== #include <iostream> #include <map> #include <cstdio> using namespace std; class Child { }; template <typename T> class Parent { private: T *m_pTemp; // ここのstaticをはずすとエラーが出ない static map<int, T*> m_Map; public: T* createChild(); }; template <typename T> T* Parent<T>::createChild() { m_pTemp = new T; // ここでエラー発生。 m_Map.insert(typename map<int, T*>::value_type(1,m_pTemp)); return m_pTemp; } int main() { Parent<Child>* pParent = new Parent<Child>(); Child* c = pParent->createChild(); printf("c:%x", c); return 0; } ==========================

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

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

テンプレートクラスでなく普通のクラスであっても、static メンバ変数はクラス定義の外側で実体を定義する必要があることはお分かりでしょうか? 同様に、このテンプレートクラスの場合も、クラス定義の外側でstaticメンバ変数の実体を定義する必要があります。 template <typename T> map<int, T*> Parent<T>::m_Map;

obake1118
質問者

お礼

定義が必要なのは理解していたのですが、教えて頂いた分の右半分しかなく、 いじくりまわしてはエラーの連続でした。 いただいた分を追加することで通るようになりました。 ありがとうございました。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

その m_Map って, どこで実体を定義してるの?

obake1118
質問者

お礼

実体の定義についてヒントを頂きありがとうございました。

obake1118
質問者

補足

お読みいただきありがとうございます。 ちなみに実体をどのように定義したらよいかでも悩んでおります。 最初は static map<int, T*> m_Map; の下あたりに Parent<Child>::m_Map; とかを入れればいけるかな?と思っていたのですが うまくいきませんでした・・・

関連するQ&A

  • C++テンプレートクラスの内部クラスについて

    テンプレートクラスについていろいろ試していたところ以下のようなコードで struct A {     struct AA { };     operator A::AA() { return A::AA(); } // (1) }; template<typename T> struct B {     struct BB { };     template<typename U>     operator B<U>() { return B<U>(); } // (2)     template<typename U>     operator typename B<U>::BB() { return typename B<U>::BB(); } // (3) }; int main() {     static_cast<A::AA>(A()); // (1) ok     static_cast<B<int> >(B<short>()); // (2) ok     static_cast<B<int>::BB>(B<short>()); // (3) compile error     return 0; } (1)と(2)はできて(3)だけがコンパイルを通りませんでした。 試したコンパイラはVC9とg++(3.3.4)とbcc32(5.5.1)で、VC9では以下のようなエラーをはきました。 「error C2440: 'static_cast' : 'B<T>' から 'B<T>::BB' に変換できません。     with [ T=short ] and [ T=int ] コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。」 (1)と(2)ができれば(3)のようなこともできそうな感じがしたのですが、他に書き方があるのでしょうか。 どなたかご存知の方がいらっしゃいましたらご教示お願いします。

  • 敬称について教えてください

    class parent{ protected final static int val=10; } class Child extends Parent{ private int val=100; public void method(String s){ System.out.println(++val)} } } class Test{ int val=10; public static void main(String args[]){ Parent c=new Child(); c.method("HELLO"); } } 初歩的な質問ですみません。教えて下さい。 上記プログラミングで、下から3行目のc.method・・・ を記入してもコンパイルエラーがおこらないのはなぜでしょうか? 今回newしているのはChildのオブジェクトです。 が、型はParentです。 Parentにはmethodはないし、 なぜこれが許されるのかがわかりません。 分かりやすくおしえてもらえませんか?

    • ベストアンサー
    • Java
  • マップとアルゴリズム

    またまた質問です。 以下の処理をさせるとエラーが出ます。 どなたか見ていただけますか? 環境はWindows XP, Visual Studio.NETです。 -----処理部分------------------ map<char, int> m; for(i=0; i<10; i++){  m.insert(pair<char, int>('A'+i, i)); } reverse(m.begin(), m.end()); map<char, int>::iterator p; p = m.begin(); while( p != m.end() ){  cout << p->first << " " << p->second << endl;  p++; } ------以下エラーログ--------------- C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。 C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(46) : コンパイルされたクラスのテンプレートのインスタンス化 'void std::swap<const _Ty1>(const _Ty &,const _Ty &)' の参照を確認してください with [ _Ty1=int, _Ty=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(45): クラス テンプレートのメンバ関数 'void std::pair<_Ty1,_Ty2>::swap(std::pair<_Ty1,_Ty2>::_Myt &)' のコンパイル中 with [ _Ty1=const int, _Ty2=int ] ClusteringMain.cpp(45) : コンパイルされたクラスのテンプレートのインスタンス化 'std::pair<_Ty1,_Ty2>' の参照を確認してください with [ _Ty1=const int, _Ty2=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。

  • 外部ファイルでのtemplate関数の実装方法

    外部ファイルでのtemplate関数の実装方法 sub.cppにtemplate関数を実装し、 main.cppで、sub.cppのtemplate関数を呼び出す、 みたいなことをやりたいのですが、 コンパイルは通りますが、リンクエラー?になってしまいます。 以下が上記のサンプルプログラムです。 //main.cpp #include <vector> #include <iostream> using namespace std; template <typename t_ret, typename t_array> t_ret sub_t(const t_array&); int main (int argc, char *argv[]) { vector<double> v; v.push_back(1.1); v.push_back(2.2); cout << sub_t<double, vector<double> >(v) << endl; return 0; } // sub.cpp #include <vector> using namespace std; template <typename t_ret, typename t_array> t_ret sub_t(const t_array& array) { return array[0]+array[1]; } //コンパイルログ main.o: In function `main': main.cpp:(.text+0x134): undefined reference to `double sub_t<double, std::vector<double, std::allocator<double> > >(std::vector<double, std::allocator<double> > const&)' collect2: ld returned 1 exit status make: *** [main] Error 1 どなたか、対処方法を教えてください。 宜しくお願いします。

  • javaの継承について

    以下のコードがある場合に、想定では「child」が出力されるとおもっていたのですが、 実際は「parent」が出力されます。 3行目でChildをnewしているので16行目のメソッドが呼び出され 画面に「child」が出力されると思っていたのですが、実行結果で その考えが違う事がわかりました。 実行結果から想定すると、3行目で定義している変数sは Parentクラスを指しているため、4行目で呼び出されるメソッドは 9行目になるのかなと思っています。 しかし、Parentクラス及びChildクラスのstaticを外すと 実行結果がchildとなります。 何故staticをつけた場合とつけない場合で実行結果が 異なるのでしょうか。 ■以下コード 1:public class samplexx { 2:  public static void main(String[] args){ 3:    Parent s = new Child(); 4:    System.out.println(s.getName()); 5:  } 6:} 7:class Parent{ 8:  public static String name ="parent"; 9:  public static String getName(){ 10:    return name; 11:  } 12:} 13: 14:class Child extends Parent{ 15:  public static String name="child"; 16:  public static String getName(){ 17:    return name; 18:  } 19:}

  • c++におけるtemplateについて

    c++の自作templateを関数宣言部と関数定義部とで、ファイルを分割する事を考えているのですが、エラーが出てtemplateをincludeすることが出来ないでいます。 例えば、 <ファイル:test.H> #ifndef test_H #define test_H #include <iostream> template<class T> class test { private: int row_, col_; public: test( int , int ); }; #endif <ファイル test.C> #include "test.H" template<class T> test<T>::test(int a, int b) :row_(a), col_(b) { std::cout << "コンストラクター" << std::endl; } <ファイル main.C> #include "test.H" #include<iostream> int main() { test a( 3, 3) return 0; } のようにtemplateファイルを分割した場合、 undefined reference to `test<double>::test(int, int)' collect2: ld returned 1 exit status のようなエラーがでます。 書籍:新c++言語入門・シニア編(下)の29章には「export」を関数定義部に付ければ良いような記述がありましたが、エラーを解決することが出来ませんでした。 main.Cにて、test.Cをインクルードするとこの問題を回避することが出来るのですが・・・。 そもそもtemplateは上記のように宣言部と定義部とを別々のファイルにすることはできないのでしょうか?

  • C++ template コンパイルできないパターン

    度々お世話になります。 以下のソースがコンパイルできません。 ご存知の方がいらっしゃれば教えて下さい。 #include <iostream> #include <exception> template<typename T, T C> inline T check(T x) { if (x == C) { throw(std::exception()); } return x; } int main() { using namespace std; int x; try { char * p = "abc"; check<char*, 0>(p); // コレがコンパイルできない int i = 2; check<int, 4>(i); // コレはコンパイルできる } catch (...) { cerr << "err" << endl; } return 0; } 手元の環境だと % g++ foo.cc foo.cc: In function 'int main()': foo.cc:18: error: no matching function for call to 'check(char*&)' となります。 関係するのか分からないのですが char* をテンプレートの引数にしているのに コンパイラのエラーメッセージは char*& となっているのがよく分かりません。 目的としては、エラーチェックをして エラーをであれば、例外を投げるというものです。

  • VC++6.0でテンプレートクラスを用いたいのですがエラーが出ます

    'CImageTemplate' : 指定の指定のテンプレート クラスはすでに定義されています と言われてしまいます. まだC++の知識が浅いのですが間違っている箇所がわかれば教えてください. ---------テンプレートのヘッダ(ImageTemplate.h)--------- template <class TempData> class CImageTemplate{ private:   TempData **Data;//データ本体   … protected:   …   InitData(int h, int w); }; ---------テンプレートのcpp(ImageTemplate.cpp)--------- #include "stdafx.h" #include "ImageTemplate.h" template<class TempData>CImageTemplate<TempData>::InitData(int h, int w) {…} ---------呼び出し側のヘッダ(ImageLabel.h)--------- #include "ImageTemplate.h" class CImageLabel{ private:   CImageTemplate < int > Label;   … }; ---------呼び出し側のcpp(ImageLabel.cpp)--------- #include "stdafx.h" #include "ImageLabel.h" #include "ImageTemplate.h" CImageLabel::InitLabel(int h, int w) { if(!Label.CheckData()){ Label.InitData(h, w); } }

  • テンプレート仮想関数のようなもの

    仮想関数をテンプレートにできないのは仕様と理解しているのですが、多少複雑になっても、それぞれの型に対するメンバ関数をいちいち記述していくことを回避するようなテクニックはありませんか? struct HOGE{ //template<typename T> //virtual operator T() = 0; //上記ができないので以下を全て記入していかなければならない virtual operator int() = 0; virtual operator short() = 0; //... }; struct HOGE1 : HOGE{ //template<typename T> //operator T() overtride{return T();} //上記ができないので以下を全て記入していかなければならない operator int(){return 0;} operator short(){return 0;} //... };

  • staticメソッドの継承

    お世話になります。 static メソッドの継承についてなのですが、 class Parent {  public static String name = "Parent";  public static getName() {   return name;  } } class Child extends Parent {  public static String name = "Child"; } だと、 Parent.getName(); Child.getName(); はともに Parent を返します。 ChildにてgetName()をオーバーライドすれば望む結果が得られるのですが、何かスマートでは無いような気がしてしまいます。 継承したstaticメソッドは親の元で実行され、そしてアクセスするstatic変数が親というのは何故なのでしょうか? 根本的な質問かもしれませんが、よろしくお願いいたします。

    • ベストアンサー
    • Java

専門家に質問してみよう