• ベストアンサー

プログラミング言語C++のエラー

#include <iostream> #include <string> using namespace std; template <typename T> T max(T n1, T n2) { if(n1 > n2) { return n1; } return n2; } int main(){ cout << max<int>(1,2) << endl; cout << max<double>(1.75,3.12) << endl; string s1 = "aiu",s2 = "eo"; cout << max<string>(s1,s2) << endl; return 0; } このコードを入力すると、添付写真のようなエラーが出ます。使用しているのはmacOSのVisual Studio codeです。明らかにいじってはいけない場所のファイル /Library/Developer/CommandLineTools/SDKs/MacOSX14.2.sdk/usr/include/c++/v1/__algorithm/max.h (添付写真のエラー表示下部のパス)が勝手に参照され、引数が一致してしまっているオーバーロードした関数となってしまいます。maxをMaxなどとすると問題は解決するのですが、既存のコードを編集する際、いちいちmaxでエラーが出ると不便です。 ちなみにテンプレートではなく、引数ごとに関数を作ればエラーは出ません。 解決方法を知っている方が居れば教えてほしいです。

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

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

へぇ・・・面白いなぁ。 最初に言っておくと、僕はC++の専門でも何でもない。 ただ、原因としては「名前空間の衝突だろうな」って事はアタリは付いた。 つまり、「std」と言うライブラリ内に既にmax、minってのが定義されてんだよ。 だから「貴方独自のmax、minを定義した」時点で、「既にstd内にmax、minがあります」ってぇんで、「名前の衝突が起きてる」のがエラーの原因なわけ。 んで、 > 解決方法を知っている方が居れば教えてほしいです。 要は名前空間をワケちまえばいいんだ。 言語仕様上は良く分からんのだが、一番簡単に思いつくのは、using namespace std;; の一行を削除することだな。 でもこれを削除すると、例えばcoutはstd::cout、endlはstd::endlと、「どこに所属したブツか」ってのを明確に書かなアカンくなる。 それよりも問題は、コンパイラに依ると思うんだけど、using namespace std;;を削除してなお、「maxは使えません」なんかの類のエラーが続けて出る場合もあり得るんだ。 少なくとも、clangみたいなコンパイラだとそうだ。従って、using namespace std;;を削除するのはあまり効果がない・・・・・・と言うか、言語仕様上どうなってるのか分からんのだけど、少なくともclangみたいなコンパイラだとそうなってる。 んで、もう一つの解決策、って言うのは「自分が定義したmax」と言うテンプレート関数を、「別名前空間内定義」として分けちゃう事だ。 例えば次のように書く。 #include <iostream> #include <string> using namespace std; namespace foo{ template <typename T> T max(T n1, T n2) { if (n1 > n2) { return n1; } return n2; } } int main(void) { cout << foo::max<int>(1, 2) << endl; cout << foo::max<double>(1.75, 3.12) << endl; string s1 = "aiu", s2 = "eo"; cout << foo::max<std::string>(s1, s2) << endl; return 0; } 例えばここでは、fooと言う名前空間を定義して、「その中で」テンプレート関数maxを定義する。そうすれが、このmaxはstdに含まれるmaxとは「違うモノなんだ」とコンパイラに教える事が出来る。 使う際にはfoo::maxになるんだけど(つまり、foo名前空間内のmaxを指定する)、これでstd::maxとは別物、と認識されるので名前の衝突は回避される筈だ。

asitanoyozora
質問者

お礼

回答ありがとうございます!たしかにusing namespace std;を消しても同じエラーが出てきました。あるサイトで勉強するためのものだったのですが、そのサイトは何かとミスが多かったのでこれも一部だと思います... そして別の名前空間を作るといった解決方法を提案してくださり、ありがとうございます!実行した結果、理想の結果になりました! 新たな発見があったので、これからの参考にもさせていただきます!

その他の回答 (1)

回答No.1

std::maxが定義されているために、どちらのテンプレートを使用すればよいのかが判断できずにエラーになっているのでしょう。 std::maxに任せてしまって問題ないのであれば、関数テンプレートの定義を削除してしまえばいいように思います。

asitanoyozora
質問者

お礼

回答ありがとうございます! サイトを見て勉強していたのですが、このサイトも何かとミスが多かったのでこれもその一種ですかね?とにかく今後は元々あった処理に任せようと思います!

関連するQ&A

  • 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という関数を作っていたので) それとも別の規則が存在したりするのでしょうか?

  • 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; } というふうにしたいんです。 テンプレート関数に引数として構造体にしてそれぞれの要素を参照する場合はどうすれば よろしいのか教えてください。 よろしくお願いします。

  • 最大値(c++)

    3つの数の最大値をArrayを使って求めるProgramを書いてます。何とかそれっぽくできたのですが、実行すると、一番初めに入れた数が最大値であると、表示されてしまいます。 なにが問題なのでしょうか? #include<iostream.h> int max(int n[], int size){ int max= n[0]; for (int i=1; i>size; i++) if(n[i]>max) max= n[i]; return max; } int main(){ int a,b,c; cout<<" 3つの数の最大値を求めます。順に3つの数字をいれてください。"<<endl; cin>>a>>b>>c; int d[]={ a,b,c }; cout<<"max :"<<max(d,sizeof d/ sizeof d[0])<<endl; return 0; }

  • C++の関数

    関数の課題が出たんですが分からないので教えてください。 第1引数と第2引数はchar型の1元配列であり、これら2つの配列(文字列)を連続して表示する関数catstringがあるものとする。 ただし第2引数にはデフォルトの文字列"あいうえお"が設定されている。main関数からキーボード入力で2つの文字列を取得し、 catstringの第1引数のみに文字列が渡される場合と第1、2引数ともに文字列が与えられるプログラムを作成せよ。 やってみましたがエラーが出てしまいます。 #include <iostream> #include <cstdlib> using namespace std; char catstring(char,char="あいうえお"); int main() { char a,b; cin>>a; cin>>b; cout<<catstring(a)<<endl; cout<<catstring(a,b)<<endl; return EXIT_SUCCESS; } char catstring(char x,char y) { char s; s=x+y; return(s); }

  • C++でどうすればcoutで表示できるのですか?

    C++についての質問です coutで表示するときに kannsuu関数の返り値を main関数とmain関数の cout << ++kannsuu(i) << endl; の部分を変更せずに kannsuu関数のみを変更して インクリメントして「2」と表示したいのですが どのようにすればいいですか? #include <iostream> using namespace std; int kannsuu(int i) {return i;} int main() { int i = 1; cout << ++kannsuu(i) << endl; return 0; }

  • C言語の質問です!

    #include "stdafx.h" #include <iostream> #include <string> #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <conio.h> using namespace std; double arrayMin(double array[][], int n){ double Min=9999999999999999999999.999999; for(int N=0;N<n;N++){ if(array[N][0]!=NULL&&array[N][0]<Min){ Min=array[N][0]; } } return Min; } double arrayMax(double array[][], int n){ double Max=-9999999999999999999999.999999; for(int N=0;N<n;N++){ if(array[N][0]!=NULL&&array[N][0]<Max){ Max=array[N][0]; } } return Max; } int main(){ double data[3][10] = {{2.0, 1.0, 5.0, 3.0, 2.0, 21.0, 4.0, 5.0, 4.0, 28.0}, {1.0, 1.0, 5.0, 3.0, 2.0, 21.0, 4.0, 5.0, 4.0, 28.0}, {3.0, 1.0, 5.0, 3.0, 2.0, 21.0, 4.0, 5.0, 4.0, 28.0}}; double min, max; min=arrayMin(data, 3); max=arrayMax(data, 3); printf("min = %lf, max = %lf\n", min, max); return 0; } 二次元配列の1行目の配列の最大値と最小値を求めることを考え,上のようなプログラムを書いたのですが, 1>.\maxmin.cpp(12) : error C2087: 'array' : 添字がありません。 1>.\maxmin.cpp(21) : error C2087: 'array' : 添字がありません。 1>.\maxmin.cpp(34) : error C2059: 構文エラー : ']' 1>.\maxmin.cpp(35) : error C2664: 'arrayMax' : 1 番目の引数を 'double [3][10]' から 'double [][1]' に変換できません。(新しい機能 ; ヘルプを参照) 1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。 というようなエラーが出てしまいます. 途中のarray[N][0]!=NULLは二次元配列dataが3行より少ない場合に対応させています. どなたかアドバイスをいただけますでしょうか? よろしくお願いいたします!

  • c++11での文字列リテラルの特殊化について

    c++11言語でのテンプレート部分特殊化についての質問です。 コメントアウト部分は出力結果です template<class T> struct VT { static const int type = 1;}; template<class T,int N> struct VT< T[N] > { static const int type = 2;}; template<class T,int N> struct VT< const T[N] > { static const int type = 3;}; template<class T> struct VT< T* > { static const int type = 4;}; template<class T> struct VT< const T*const > { static const int type = 5;}; #include<iostream> #include<typeinfo> int main(){ std::cout<<"A:"<< VT< char >::type << std::endl; // A:1 std::cout<<"B:"<< VT< char[10] >::type << std::endl; // B:2 std::cout<<"C:"<< VT< char* >::type << std::endl; // C:4 std::cout<<"D:"<< VT< char const [1] >::type << std::endl; // D:3 std::cout<<"E:"<< VT< decltype("") >::type << std::endl; // E:1 std::cout<<"G:"<< typeid( char const [1] ).name() << std::endl;// G:char const [1] std::cout<<"H:"<< typeid( "" ).name() << std::endl;// H:char const [1] } 型名を直接記述したD,G、文字列リテラルを記述したE,H。 コンパイラ毎の差はあれど、GとHの型名は同じものが表示されます。 ですが、[D:3] [E:1]と値は違い、別の特殊化テンプレートが使われています。 この部分が分かりません。 また、配列リテラル、文字列リテラルに対し部分特殊化テンプレートを宣言する方法などありましたら、ご教示お願いします。

  • C言語/プログラミング

    int Sutar(int i, int j) { for (i = 1; i <= 5; i++) { for (j = 0; j < i; j++) { cout << "★¥n"; } cout << "¥n"; } return i, j; } int main() { int i; cout << "★を何個出力しますか?¥n"; cin >> i; cout << "★を" << Sutar(i, j) << "個出力に成功しました。¥n"; return 0; } これで、実行したらエラー発生しました。エラーを治す方法を教えてください。

  • C言語/プログラミング

    int Trianglearea(int x, y) { return x * y / 2; } int main() { int x, y, ans; cout << "底辺を入力してください。\n"; cin >> x; cout << "高さを入力してください。\n"; cin >> y; cout << "三角形の面積は" <<Trianglearea(x, y) << "です。\n"; return 0; } これで、実行したらエラー発生しました。エラーを治す方法を教えてください。

  • 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は上記のように宣言部と定義部とを別々のファイルにすることはできないのでしょうか?

専門家に質問してみよう