• ベストアンサー

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*& となっているのがよく分かりません。 目的としては、エラーチェックをして エラーをであれば、例外を投げるというものです。

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

  • ベストアンサー
  • MrBan
  • ベストアンサー率53% (331/615)
回答No.7

> 多分、他に書き方がないんでしょうね 原文ですが(JISはしらない)、例えば同列の「pointer to member ..."」などと異なり、 こちらの規定では"the address of ..."なあたりもポイントかと。 # 私も当初、ML側で説明がある程度の認識だったのですが、 # ちゃんと読むと、この部分の規定はポインタではなくアドレス。 > これだと, NULL と比較できないので 私も昨日少し考えましたが、多分、綺麗なNULL比較はパラメータでは無理なんじゃないかと。 > char * xa[] = {0}; xaをnull_exprとか命名すると多少はましになるかもしれませんが、 私なら多分テンプレートの第二引数を省略した版を作ります(↓)。 > という事で、やっぱり似たような専用の記述を複数書くのが > 無難なような気がしてきました。 template<typename T, T c> // 本当はT c=0にしたいが0はintなので… // [0比較用のオーバロード] cを省略すると、最も頻度の高そうな0と比較 // オーバロードでなくcheck_zeroとかそんな名でもいいですが…。 template<typename T> inline T check(T x) { if (x == 0) { throw std::exception(); } // できれば、この用途にstd::exceptionは派生させておくべきかと。 // でないと受け側catchで原因が特定できない check<int, 4>(i); check<char*>(p); // 0比較 // もしかするとこんなのもありか。template<typename T*, int p> // でもcheck<int*, 0x80000000>とか書くとunsigned longだなぁ。 > なんだか、実用というより自分の興味本位な内容になってしまってすみません。 私も趣味/興味で調査してますから(C++が好きなんです) # cppllに反応すれば、私なら素直にRaiiで例外出すか、 # Raiiの「ポリシー」にする気がします。(このcheckがポリシー用?)

hi-mi-tsu
質問者

補足

ありがとうございます。 > template<typename T> > inline T check(T x) { > if (x == 0) { > throw std::exception(); > } そうですね。 こういう感じですね。 // できれば、この用途にstd::exceptionは派生させておくべきかと。 // でないと受け側catchで原因が特定できない あぁこれは、もともと自分もそうしようとしていて template<typename E, typename T> ... throw E(); ... という感じにしようかと思っていました。 ただ、あまり元々質問の本質と関係ないと思ったので 混乱されたくなかったので省略していました。 > // もしかするとこんなのもありか。template<typename T*, int p> > // でもcheck<int*, 0x80000000>とか書くとunsigned longだなぁ。 ここは、よく分かりませんでした。 > # cppllに反応すれば、私なら素直にRaiiで例外出すか、 > # Raiiの「ポリシー」にする気がします。(このcheckがポリシー用?) Raiiの「ポリシー」というのが、イメージ沸かなかったのですが。 例外については、Kent.N さんも書かれていますが、 一旦 Raii のコンストラクタに入る前に、 止めたいというのがあります。 デストラクタで気を使う必要が出そうなので。 > 私も趣味/興味で調査してますから(C++が好きなんです) それは安心しました。

その他の回答 (6)

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.6

# cppllも(別ハンドルですが)入ってますのでそちらの流れも把握しています。 JIS X3014でも章番号は一緒ですので、それを頼りにしてもらえれば、 ここで見るべきは以下ですね。 14.3.2 Template non-type arguments ・"& 識別式" 形式(※)で表され外部リンケージを持つオブジェクトまたは関数のアドレス  ※もし名前(識別式)が関数/配列をさすか、テンプレートパラメータが参照の場合には'&'は省略可能 なお、[--snip--]としていた部分は例外規定で、 「関数テンプレートと関数テンプレート識別子は含まれるが非静的なクラスメンバは含まない」 と書いてあります。 また、上記のポインタ規定以外でテンプレート引数として認められているのは、 ・整数型または列挙型の整数定数式 ・型でないテンプレート引数の名前 ・5.3.1章で規定のメンバへのポインタ だけで、「上記のいずれかでなければならない(shall)」と書いてあります。 また、その後に変換規定があり、それらに合致しない場合もill-formedとのことです。 > 1.関数と配列の & は省略できる。(アドレスの為の &) > 2.テンプレートに関数、配列を使う場合はリファレンスになる > ということでしょうか? ポイントはそこではなく、「"& 識別式" の形式で表され」の部分かと思います。 単に"x"ではだめで、"&x"になるような形でなければならないとなっており、 (多分コンパイル時定数の保証のための規定?) ここで、xはchar*であって'&'を省略できる条件を満たしませんので、 リンケージだけを外部にしてもダメということになります。 # 規格書の例では、文字列リテラル("Vivisectionist")すらchar配列に格納しないとエラー。 # MinGW3.2で試してみると、グローバル変数で確かに # char x[] = "foo";だと配列なので単に"x"でもコンパイルが通ります。 # char* x = "foo";にしたら通らなくなりました。

hi-mi-tsu
質問者

補足

何度も本当にありがとうございます。 > ポイントはそこではなく、「"& 識別式" の形式で表され」の部分かと思います。 > 単に"x"ではだめで、"&x"になるような形でなければならないとなっており、 > (多分コンパイル時定数の保証のための規定?) > ここで、xはchar*であって'&'を省略できる条件を満たしませんので、 > リンケージだけを外部にしてもダメということになります。 MinGWの挙動が正しいと言われていた理由が理解できました。 規格のこの部分の表現は少しトリッキーに感じました。 「"& 識別式" の形式で表され」でも &を省略できる場合があるよ というような部分に、 多分、他に書き方がないんでしょうね > # char x[] = "foo";だと配列なので単に"x"でもコンパイルが通ります。 こっちはg++もコンパイルできました。 これだと, NULL と比較できないので template<typename T, T * C> inline T check(T x) { if (x == *C) { throw std::exception(); } return x; } char * xa[] = {0}; int main() { ... check<char*, xa>(p); ... } などとやってみました。 ただこれだと、checkがintにも使える汎用性もなくなりますし、 check の中では NULL を使ってるのではなくて xa を使っているので 最適化の視点からは微妙ですね。(こういう事に、無意味にこだわっている自分の頭の方がおかしいとは思っているんですが。。。。) また、 char * const xa[] = {0}; とすれば、最適化の可能性も出てくるかと思ったのですが テンプレートの引数のところをいろいろ試してみても、 コンパイルできませんでした。 コンパイル通ってもいろいろ微妙なので、これはできなくてもいいかなと思います。 char * xa[] = {0}; の方法を考えなおすと 1. check で int を使えなくなるので微妙 2. 最適化できない。 3. xaを書換えられるかもしれない 4. 外部リンケージなので static char * xa[] = {0}; はダメで xa がグローバルになる。(namespaceはできましたが) という事で、やっぱり似たような専用の記述を複数書くのが 無難なような気がしてきました。 なんだか、実用というより自分の興味本位な内容になってしまってすみません。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.5

# 指摘を受けて「お?」と思い再確認したら、テストコードがバグってました…orz # 突貫作業はダメだ…すみません。 MinGW3.2では、外部リンケージにしてもエラーになりました。 Bccの方は、外部リンケージにすれば通るようです。 ただ、規格を厳格に読む限りMinGWの挙動の方が正しそうです(expressed~以降) <ISO/IEC 14882> the address of an object or function with external linkage, [--snip--], expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference </ISO/IEC 14882> # 規格書は、凄く見にくい/微妙に内容が違う日本版(JIS X3014)でよければ、 # オンラインで閲覧可能です(ISOの方は売り物)。見にくいので私はISOの方しか見てませんが。 # cppllでも以前話題になってます(こちらは私も見てます)。

参考URL:
http://ml.tietew.jp/cppll/cppll/thread_articles/11432
hi-mi-tsu
質問者

補足

ありがとうございます。 体調悪かったのでしばらく寝てました。 cppllの方にも質問してみました。 http://ml.tietew.jp/cppll/cppll/article/12933 > # 指摘を受けて「お?」と思い再確認したら、テストコードがバグってました…orz > # 突貫作業はダメだ…すみません。 gcc 3.2 の方は、ダメだったというより コンパイルできませんでした。 4.1.1 で 3.2 をコンパイルするのが変なのかもしれません。 あまりはまっても仕方ないので諦めました。 > <ISO/IEC 14882> 英語はあまり分からないのですが、 1.関数と配列の & は省略できる。(アドレスの為の &) 2.テンプレートに関数、配列を使う場合はリファレンスになる ということでしょうか? だとすると、Bcc が正しいような気がします。 > # 規格書は、凄く見にくい/微妙に内容が違う日本版(JIS X3014)でよければ、 > # オンラインで閲覧可能です(ISOの方は売り物)。見にくいので私はISOの方しか見てませんが。 見にくい方しか見てないので、なんとも言えないですが 文章の構成が頭に入ってないと見るところの、的が絞れそうにありませんでした。 目次もないみたいでしたし。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.4

「templateの非タイプパラメータにアドレスを渡す場合、 外部リンケージを持っていないといけない」規定(ISO/IEC14882 $14.3.2 1)に 抵触してて、(char*)0ではダメなんですね。 # VCの引数解釈で0特別扱いはまずいとして、(char*)0もまずいのか…。 # 単純に「型不一致」と「コンパイル定数か否か」の問題かと誤認してました>自分…orz > char * p = "abc"; > char * const x = 0; > check<char*, x>(p); というわけで、これは、xをグローバルに宣言すると通りました(MinGW)

hi-mi-tsu
質問者

補足

何度もありがとうございます。 > というわけで、これは、xをグローバルに宣言すると通りました(MinGW) おぉ、そうなのですか! 実は、これもやってはいたのですがこっちではダメでした。 そういえば、gccは3.3.6 も持っていたのですが こっちもダメでした。 とりあえず、gcc 3.2 をコンパイルしています。 MinGWのバージョンと互換性があるのかは分からないですが。 > 「templateの非タイプパラメータにアドレスを渡す場合、 > 外部リンケージを持っていないといけない」規定(ISO/IEC14882 $14.3.2 1)に > 抵触してて、(char*)0ではダメなんですね。 なるほど、規格は持ってないのですが 3.2でダメなら、gccのバグ(<-良く分かってない人が使いがちなフレーズ) かもしれないので、 cppllとgcc本家にあたってみようかと思います。

  • colder
  • ベストアンサー率43% (30/69)
回答No.3

規格書14.3.2/5により、不適格なプログラムです。 > 0 は、汎整数型の非型のテンプレート仮引数に対する正当な《テンプレート実引数》であるが、 > ポインタ型の非型のテンプレート仮引数に対する正当な《テンプレート実引数》ではない。

hi-mi-tsu
質問者

お礼

回答ありがとうございます。 不適格なプログラムですかぁ。 テンプレートでのやり方はなさそうですね。 あとはマクロですかね。 一応直接 0 でなくて char * p = "abc"; char * const x = 0; check<char*, x>(p); ともやってみたのですが % g++ hoge.cc hoge.cc: In function 'int main()': hoge.cc:37: error: 'x' cannot appear in a constant-expression hoge.cc:37: error: no matching function for call to 'check(char*&)' となるようでした。 intのconstはコンパイルできるようでしたが int i = 2; int const x = 4; check<int, x>(i);

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.2

GCC(g++)のバージョンはいくつですか? VC7.1SP1では、提示のままのソースでコンパイル通りました。 VC8も通ります。 MinGW(g++)3.2ではエラー。 ・no matching function for call to check(char*&) Bcc5.6でもエラー。 ・check<T,C>(T)からテンプレート特化できない ・check<T,C>(char*)に一致するものが見つからない 但し、Bccはcheck<char*, (char*)0>(p);に直すと通ります。 MinGWは相変わらずで、以下のエラーになります。 ・'0' is not a valid template argument ・it must be the address of an object with external linkage ・no matching function for call to check(char*&) C++でNULLに相当する0は、型としてはintです。 単にcheck<char*, 0>と書くと、型はcheck<char*,int>と扱われるため、 0(int)⇒char* Cが暗黙で変換できない(reinterpret_castが必要なはず)ので、 合致しないと言われているかと思います。 (ちなみに、VC7.1においても、0⇒1にする(check<char*,1>)はエラーなので、 ・型キャスト' : 'int' から 'char *const ' に変換できません。 ・テンプレート引数 'int' が無効です。 0(NULL)だけ特別扱いするような特殊則があると思われます。 GCC(g++)でキャストしてもエラーになる理由は不明です。 # 3.2は古い代物なので、GCCのバージョン問題かも…。

hi-mi-tsu
質問者

お礼

いろいろ調べてもらってありがとうございます。 > GCC(g++)のバージョンはいくつですか? 4.1.1 です。 (リリースの最新より1つ前みたいです) > C++でNULLに相当する0は、型としてはintです。 自分もこの点が気になったので、char* にキャストしてみたんですが % g++ hoge.cc hoge.cc: In function 'int main()': hoge.cc:32: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression hoge.cc:32: error: no matching function for call to 'check(char*&)' となりました。 エラーメッセージを見る限り、 整数かenum以外へのキャストは constantな文(=>テンプレートの引数)に入れられない。 ということみたいですね。 gcc以外では通るようなので、 規格としてダメなのか、gccだけダメなのかは分からないですが(もしくは未定義) reinterpret_castは、関数で実行時なのかもしれないと、 思ったのですが、先に inline展開 するのかもしれないですが 同じエラーでした。 > ・型キャスト' : 'int' から 'char *const ' に変換できません。 上に書いたgccの 整数かenumへのキャストの件もこの事をいってるのかもしれないですね。 このキャストはコンパイル時でなくて、実行時での取り扱いなのかもしれませんね

  • neKo_deux
  • ベストアンサー率44% (5541/12319)
回答No.1

> char* をテンプレートの引数にしているのに いえ。 > template<typename T, T C> > inline T check(T x) { > if (x == C) { > throw(std::exception()); > } > return x; > } 実体の引数を受け取るものしか準備されていません。 char*を渡したいのなら、char*を受け取れる関数を準備しておく必要があります。

hi-mi-tsu
質問者

補足

回答ありがとうございます。 せっかく回答を頂いのですが、回答の意味を理解しきれていません。 すみません。 > 実体の引数を受け取るものしか準備されていません。 > char*を渡したいのなら、char*を受け取れる関数を準備しておく必要があります。 char* 専用に以下のようなものは作ってみたのですが、状況は変化しませんでした。 template<char *, char * C> inline char * check(char * x) { if (x == C) { throw(std::exception()); } return x; } char *& でも、コンパイルできませんでした。 template<char *&, char *& C> inline char *& check(char *& x) { if (x == C) { throw(std::exception()); } return x; } ... int main() { ... check<char*&, 0>(p); ... } 多分これでは、char* を受けとれないということなのですよね。 この部分の書き方を教えて頂けないでしょうか? さすがにtemplateを止めるとコンパイルできました。 inline char * check(char * x) { if (x == 0) { throw(std::exception()); } return x; }

関連するQ&A

  • テンプレートクラス中のフレンドクラス

    下記をg++(fedora core1)でコンパイルしたところ、 #include <iostream> using namespace std; template< typename T > class A {   T a; public:   A(T aa ) : a(aa) { }   friend ostream& operator<<( ostream &os, const A &a ); //9行目 }; template< typename T > ostream& operator<<( ostream &os, const A<T> &a ) { return os << a.a; } int main( ) {   A<int>  a(5);   cout << a << '\n';   return 0; } 9行目にこのような警告・エラーが出てコンパイルできませんでした。(下記のオプションも試してみましたがダメでした) friend declaration 'std::ostream& operator<<(std::ostream&, const A<T>&)' declares a non-template function (if this is not what you intended, make sure the function template has already been declared and add<> after the function name here) -Wno-non-template-friend disables this warning. :undefined reference to 'operator<<(std::basic_ostream <char, std::char_traits<char> >&, A<int> const&)' なぜ、コンパイルできないのかが分かりません。ちなみに、bcc32(borland c++ compiler5.5.1)では同様のエラーが出てコンパイルできず、cl(VC++6.0)ではコンパイル・実行可能でした。 ご存知の方いらっしゃったらご教授お願いします。(bccとclはWinXPです)

  • 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++テンプレートでの引数

     こんにちは。 今回は、C++ テンプレートで引数に構造体を使えないか悩んでいます。 例えば #include <stdio.h> typedef struct _rect{ int x; int y; }RECT; typedef struct _rect{ double x; double y; }DATA; template <calss T> T Function(T abc) { // 構造体の要素にも対応している。 cout << abc//の要素x << endl; cout << abc//の要素y << endl; return T; } int main() { RECT t; DATA r; t.x = 80; t.y = 90; t = Function(t); // こういった事をしたい r = Function(r); return 0; } というふうにしたいんです。 テンプレート関数に引数として構造体にしてそれぞれの要素を参照する場合はどうすれば よろしいのか教えてください。 よろしくお願いします。

  • clock関数のコンパイルエラーで

    こんにちは。 C++プログラムの実行時間計測リスト #include<iostream.h> #include<time.h> int main(void){ clock_t start_time=clock(); int i; //ココから //計測したい処理を書く //ココまで cerr<<clock()-start_time<<"マイクロ秒"<<endl; return 0; } をRedHat9上でコンパイルしようとすると $gcc -o clock clock.cc /usr/include/c++/3.2.2/backward/iostream.h:31 から include されたファイル中, clock.cc:1 から: /usr/include/c++/3.2.2/backward/backward_warning.h:32:2: 警告: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <sstream> instead of the deprecated header <strstream.h>. To disable this warning use -Wno-deprecated. /tmp/ccoZe32a.o(.text+0x1c): In function `main': : undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)' /tmp/ccoZe32a.o(.text+0x3b): In function `main': : undefined reference to `std::cerr' /tmp/ccoZe32a.o(.text+0x40): In function `main': : undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(long)' : collect2: ld はステータス 1 で終了しました となってしまいます。これはどうすればコンパイルできるようになるのでしょうか?

  • MingwでC++のソースがコンパイルできない。

    質問があるのですがよろしくお願いしします。 プラットフォームは Windows HOME です。 MinGWでC++のhelloworld.cppという名前のプログラム ------ここから----------- #include <iostream> using namespace std; int main(){ cout <<"Hello World!!\n"; return 0; } -------ここまで----------- を、gcc helloworld.cpp とWindowsのコマンドプロンプトから打ってコンパイルしようとしたのですが、 undefined reference to std string::size() const undefined reference to std string::operator[](using int) const undefinrd reference to std::cout undefinrd reference to std::basic_ostream<char, std::char traits<char> >&, char const*) undefinrd reference to std::ios_base::Init::() undefinrd reference to std::ios_base::~Init::() などのエラーが出て、コンパイルできません・・ hello.cという名前のC言語プログラム --------ここから------ #include<stdio.h> int main(void){ printf("Hello GCC World on Windows!!\n"); } ------ここまで------- は、gcc hello.c で正常にコンパイルでき、生成したexeファイルも正常に動きます。 また、eclipse CDT上からc++プログラムをMinGWでコンパイルすることもできるのですが・・ なぜかWindowsのコマンドプロンプトからc++プログラムをコンパイルしようとするとエラーが出てしまいます。(C言語のプログラムでもエラーが出ることが時々あります。) どなたか詳しい方いらっしゃいましたらご教授頂けると幸いです。 よろしくお願いします。

  • Visual C++ Toolkitでcppをコンパイルすると・・

    最近質問が多くてすみません。 一応調べてみましたが、同じような質問が既存ならば警告お願いします。 #include <iostream> int main(){ return 0; } これだけのファイルを、例えばtest.cppとして保存します。そして cl test.cpp とすると、ぶわーっと警告(warning)がでて、しかしtest.exeができあがります。 警告内容がかなり長いので、そのうちの1つを載せます。 C:\Program Files\Microsoft Visual C++ Toolkit 2003\include\stdexcept(39) : see reference to class template instantiat ion 'std::basic_string<_Elem,_Traits,_Ax>' being compiled with [ _Elem=char, _Traits=std::char_traits<char>, _Ax=std::allocator<char> ] 意味がわかりません!! ちなみに、bccでは警告なしにコンパイルできます。

  • c++テンプレート関数名

    #include <iostream> #include <string> using namespace std; template <class T> T maxdt std(T a,T b){ if (a>b) return a;else return b; } int main (){ int id1,id2,n1 = 1000,n2 = 2000; double ddt; string sdt,s1 = "abcd",s2 = "jklm"; id1 = maxdt(n1,n2); id2 = maxdt(3000,4000); ddt =maxdt (55.55,66.66); sdt = maxdt(s1,s2); cout << "id1" << id1 <<endl; cout << "id2" << id2 <<endl; cout << "ddt" << ddt <<endl; cout << "sdt" << sdt <<endl; return 0; } というプログラムが例題であり、僕は横着をしてmaxdtをmaxという名前としてプログラムを作ったところ、 オーバーロード関数の呼び出しがあいまいです。 というエラーが表示されコンパイルできませんでした。 環境はubuntu 12.04,gcc 4.6.3 g++でコンパイルしました。 ググってもテンプレート関数の名前の付け方に規則は存在していないようなのですが、 これは直前に作ったプログラムの影響でしょうか?(maxという関数を作っていたので) それとも別の規則が存在したりするのでしょうか?

  • 外部ファイルでの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 どなたか、対処方法を教えてください。 宜しくお願いします。

  • C++の関数テンプレートで分からないところがあります。

    C++の関数テンプレートで分からないところがあります。 C++の入門書を読んで勉強しているのですが、その演習問題(答えはついてないです)で、以下のような問題がありました。 ----------------------------------------------------- 配列の全要素の最小値を求める関数テンプレートを作成せよ。 teplate <class Type> Type minof(const Type x[], int n); という形で作ること。 なお、最も小さい文字列を求められるようにするために、const char *型に明示的に特殊化したものも合わせて作成すること。 ------------------------------------------------ という問題なのですが、これにたいして僕は以下のように答えました。ヘッダのインクルードなどは省きます。 template<class Type> Type minof(const Type x[], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(x[min] < x[i])             min = i;     return x[min]; } template<> const char* minof<const char *>(const char x[][64], const int n) {     int min = 0;     for(int i = 1; i < n; i++)         if(strcmp(x[min], x[i]) < 0)             min = i;     return x[min]; } int main() {     const int n = 5;     int a[n];     char s[n][64];     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> a[i];     }     cout << "文字列\n";     for(int i = 0; i < n; i++){         cout << i + 1 << "番目---";         cin >> s[i];     }     cout << "整数の最小値---" << minof(a, n) << "です\n";     cout << "文字列の最小値---" << minof<const char *>(s, n) << "です\n"; } これをコンパイルすると、エラーで 明示的な特殊化; 'const char *minof<const char*>(const char [][64],const int)' は関数テンプレートの特殊化ではありません と 'minof' : 1 番目の引数を 'char [5][64]' から 'const char *const []' に変換できません。 とでてしまいます。 色々探してみたのですが、解決できませんでした・・。 特に最初のほうのエラーがよくわかりません。ちゃんと特殊化してる気はするのですが・・。 間違っている箇所の正当を載せていただけるとわかりやすくて、ありがたいです。 よろしくお願いします!

  • C++がコンパイルできない...

    非常に初歩的な問題で恐縮なのですが、以下のようなシンプルなプログラムでコンパイルが出来ず困っております。 何がいけないのか、もしくは何をチェックすればよいかを教えて下さい *_*; program #include <iostream.h> int main(void){ cout << "matumoto"; } ---- 最初 void main(void)とした所、怒られたため、int ...としましたが、更に以下のようなエラーが出力されてしまいました 未定義の 最初に参照している シンボル ファイル std::ios_base::Init::~Init [in-charge]()/var/tmp//ccxj7cux.o std::ios_base::Init::Init[in-charge]()/var/tmp//ccxj7cux.o std::cout /var/tmp//ccxj7cux.o std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)/var/tmp//ccxj7cux.o __gxx_personality_v0 /var/tmp//ccxj7cux.o ld: 重大なエラー: シンボル参照エラー。a.out に書き込まれる出力はありません。 collect2: ld returned 1 exit status [環境] Solaris 8 gcc %>>gcc -ver Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.8/3.3/specs Configured with: ../configure --disable-nls --with-as=/usr/ccs/bin/as --with-ld=/usr/ccs/bin/ld Thread model: posix gcc version 3.3 すみませんが、宜しくお願い致します。