コンパイルエラー。間違ってるのは誰?(どこ?)

このQ&Aのポイント
  • template<typename T>クラス内で定義されたfriend関数にてコンパイルエラーが発生しています。エラーメッセージによると、引数の型変換に関連してエラーが起こっているようです。
  • コンパイルエラーは、変換コンストラクタがconst修飾されたRational<T>型をRational<T>&型に変換できないというエラーが原因です。
  • このエラーを回避するためには、friend関数の引数にconst修飾と参照を外す必要があります。これは、コードが誤った型変換をしているのではなく、テンプレートクラスの仕様に関連したエラーです。
回答を見る
  • ベストアンサー

コンパイルエラー。間違ってるのは誰?(どこ?)

Effective C++の「型変換をさせたいなら、メンバでない関数をクラステンプレートの中で定義しよう」という項目に乗っていたコードを実験してみたのですが、コンパイルでエラーが出るようです。 ----- template<typename T> class Rational { T numerator_value; T denominator_value; public: Rational(const T& num=0, const T& den=1) :numerator_value(num), denominator_value(den){} const T numerator(){return numerator_value;} const T denominator(){return denominator_value;} void show() const { std::cout<<"numerator="<<numerator_value<<": denominator="<<denominator_value<<std::endl; } friend const Rational operator*(const Rational& lhs, const Rational& rhs) //←引数がおかしい? { return Rational(lhs.numerator()*rhs.numerator(), lhs.denominator()*rhs.denominator()); } }; int main() { Rational<int> obj1(1,10); Rational<int> obj2; obj2=obj1*10; obj2.show(); return 0; } ----- こういうコードを書いたのですが、friend関数の部分で「'const Rational<T>' から 'Rational<T> &' へ 'this' ポインタを変換できません」等と怒られます。 引数に取る二つの値のどちらもおかしいようで、コンパイルのエラーを出さないようにするためには、constと&を外さないといけないようです。 引数はEffectiveC++の掲載コードをそのまま使っています。 これは、私のコードがおかしいのか、本のコードがおかしいのかどちらでしょうか?

  • sirn
  • お礼率41% (43/103)

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

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

> コンパイルのエラーを出さないようにするためには、constと&を外さないといけないようです。 関数 numerator() / denominator() が const になってないからでは?

sirn
質問者

お礼

ああ、そういえば......orz その通りで御座います。 回答ありがとう御座いましたm(__)m

関連するQ&A

  • メタ関数の再帰停止の方法についての質問です.

    メタ関数の再帰停止の方法についての質問です. 最大公倍数を求めるメタ関数を作ろうとして引数をintに固定したものはすぐ作れたのですが 引数を任意の整数にしたものを作ろうとしたところ,いろいろな方法を試みましたがどれもだめで結局以下のようにしました. template<typename IntegerT, IntegerT Rhs, IntegerT Lhs> struct gcd; template<int Rhs, int Lhs> struct gcd<int, Rhs, Lhs> { typedef int integer_type; typedef gcd<integer_type, Rhs, Lhs> type; typedef integer_type value_type; static const value_type value = gcd<integer_type, Lhs, Rhs % Lhs>::type::value; }; template<int Rhs> struct gcd<int, Rhs, 0> { typedef int integer_type; typedef gcd<integer_type, Rhs, 0> type; typedef integer_type value_type; static const value_type value = Rhs > 0 ? Rhs : -Rhs; }; template<long long Rhs, long long Lhs> struct gcd<long long, Rhs, Lhs> { typedef long long integer_type; typedef gcd<integer_type, Rhs, Lhs> type; typedef integer_type value_type; static const value_type value = gcd<integer_type, Lhs, Rhs % Lhs>::type::value; }; template<long long Rhs> struct gcd<long long, Rhs, 0ll> { typedef long long integer_type; typedef gcd<integer_type, Rhs, 0ll> type; typedef integer_type value_type; static const value_type value = Rhs > 0ll ? Rhs : -Rhs; }; しかし,この方法だと考えられる整数全てに対して特殊化を定義せねばならず何のためにテンプレートを使っているのかわかりません. テンプレートのインスタンス化の順序を考えてみるとコンパイル時に再帰を停止するための条件が普通に考えたものとは異なるように思うのですが,どのようにすればもっと簡単に一般の整数型(short,long等)に対してメタ関数を定義できるでしょうか?

  • std::lower_boundについて

    こんにちは。 std::vector< int* > IntArray; IntArray.push_back( new int( 0 ) ); IntArray.push_back( new int( 2 ) ); IntArray.push_back( new int( 1 ) ); IntArray.push_back( new int( 6 ) ); IntArray.push_back( new int( 5 ) ); IntArray.push_back( new int( 7 ) ); というint型のポインタが格納されているIntArrayを bool cmp( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::sort( IntArray.begin(), IntArray.end(), cmp ); として並べ替えたとします。 そこで新しく new int( 4 )をソートされた順番を壊さない位置に挿入したいと思いlower_boundを使用しようと思いました。 しかし、lower_boundの使い方がいまいちわかりません。 int *p = new int( 4 ); bool cmp2( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::lower_bound(  IntArray.begin(),  IntArray.end(),  p,  cmp2 ); 上記のように使用すればこの場合だと変数pを挿入する位置が返ってくるのでしょうか? 間違えているとしたら、どのように修正すれば変数pを挿入できる位置が返ってくるように書き直すことができるでしょうか?(むしろそういった実装は可能なのでしょうか) よろしくお願いします。 今回は特殊ケースでの問題ですのでint* pをintに修正する、挿入してから再度ソートする、といったことはなしでお願いします。あくまでもlower_boundで実装する場合のコードについてでよろしくお願いします。 /*   VisualStudio 2008 academic edition   Window7 64bit */

  • C++のvectorについて教えてください。

    C++のvectorについて教えてください。 現在悩んでいる問題について簡単に説明するために、テストコードを書きました。 #include <vector> class IntType { private: int num; public: IntType( int n ):num( n ){}; }; std::vector< IntType > IntVector; void main() { } このコードをDebug版でコンパイルすると 1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(285) : error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : テンプレート 引数を 'const std::reverse_iterator<_RanIt> &' に対して 'const size_t' から減少できませんでした 1> c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(2236) : 'std::operator <' の宣言を確認してください。 のようなエラーが出ます。 しかし、Release版でコンパイルするとコンパイルは通ります。 Debug版でコンパイルを通すにはどのようなコードを追加すればよいでしょうか? 知恵を貸してください。 よろしくおねがいします。 /** VisualStudio2008 AcademiEdition */

  • こんなコンパイルエラーがでます。

    OS:WinNT4.0 環境:VC++6.0 MFC コンパイル時に次のエラーが出て来ました。 error C2664: 'qsort' : 4 番目の引数を 'int (const void *,const void *)' から 'int (__cdecl *)(const void *,const void *)' に変換できません。 (新しい機能 ; ヘルプを参照)スコープ内でこの名前を持つ関数でターゲット型に一致するものはありません。 qsort関数の引数関数を'int xxxxxxx(const void *,const void *)に宣言したところこのエラーが出てきました。 何がなんだかさっぱりわかりません。 ぜひお願いします。

  • 演算子オーバーロードのプログラムで

    今、C++でテンプレートクラスや演算子オーバーロードを使ったプログラムの練習をしているのですが、どうしてもうまく動かなく質問させてもらうことにしました。 大まかに言えば、int型のvalueを持ったDataというクラスを用意し、演算子+と-のオーバーロードによって、クラスの足し算引き算を可能にしよう。ということなのですが、 それぞれのオーバーロードした演算子ともに、addSubtractという+と-両方に対応した関数を呼ぶことで使おうと思っています。 コードは以下のようになっています。 1 #include <iostream> 2 3 using namespace std; 4 5 template<class Comparable> 6 class Data { 7  public: 8   Data(){value = 0;} 9   Data(int i){value = i;} 10   int value; 11   Data<Comparable> operator+(const Data<Comparable> &); 12   Data<Comparable> operator-(const Data<Comparable> &); 13   Data<Comparable> Data<Comparable>::addSubtract(const Data<Comparable> & rhs, int sign); 14 }; 15 16 template<class Comparable> 17 Data<Comparable> Data<Comparable>::addSubtract(const 18 Data<Comparable> & rhs, int sign) { 18   int value1=this->value; 19   int value2=rhs.value; 20   Data<int> result(value1+(sign*value2)); 21   return result; 22 } 23 24 template<class Comparable > 25 Data<Comparable> Data<Comparable>::operator+(const Data<Comparable> & rhs) { 26   return addSubtract(&rhs, 1); 27 } 28 29 template<class Comparable > 30 Data<Comparable> Data<Comparable>::operator-(const 31 Data<Comparable> & rhs) { 31   return addSubtract(&rhs, -1); 32 } 33 34 int main() { 35   Data<int> matrix1(2); 36   Data<int> matrix2(1); 37   cout<<"data1:"<<matrix1.value<<endl; 38   cout<<"data2:"<<matrix2.value<<endl; 39 40   Data<int> result1 = matrix1+matrix2; 41   cout<<"data1+data2"<<result1.value<<endl; 42 43   Data<int> result = matrix1-matrix2; 44   cout<<"data1-data2"<<result2.value<<endl; 45 } このコードを実行したところ、以下のようなエラーメッセージが表示されて動かすことができません。 add.cpp:41: instantiated from here add.cpp:26: error: invalid conversion from `const Data<int>*' to `int' add.cpp:26: error: initializing argument 1 of Data<Comparable>::Data(int) [with Comparable = int]' アドバイスをいただけるとありがたいです。

  • コンパイルエラー

    コンパイルしても、12行目(printf("%d番目の整数を入力してください。"i+1);が、関数呼び出しに)がないとでます。でもどこが間違っているか分かりません。 教えてください。お願いします。 #include <stdio.h> int main(void) { int num; int sum=0; int i; for(i=0; i<10; i++){ printf("%d番目の整数を入力してください。"i+1); scanf("%d", &num); sum+=num; } printf("合計は、%dです。\n", sum); return(0); }

  • コンパイルエラー

    前に質問したものですが、ちょっとソースをいじりました。 ファイルから読み込んだデータ文字列をキゅーにエンキゅーしたりできゆーしたりするプログラムを作っています。 コンパイルできて実行できました。 でもエンキューとデキューが実行されてません。 次のソースのうちどこを変えたらいいか教えてください #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUMBER 100 /*--- キューを実現する構造体 ---*/ typedef struct { int max; /* キューのサイズ */ int num; /* 現在の要素数 */ int front; /* 先頭要素カーソル */ int rear; /* 末尾要素カーソル */ char (*que)[NUMBER]; /* キュー(の先頭要素へのポインタ) */ } Queue; /*--- キューの初期化 ---*/ int QueueAlloc(Queue *q, int max) { q->num = q->front = q->rear = 0; if ((q->que = calloc(max*20, sizeof(char))) == NULL) { q->max = 0; /* 配列の確保に失敗 */ return (-1); } q->max = max; return (0); } //--- キューの後始末 --- void QueueFree(Queue *q) { if (q->que != NULL) { free(q->que); // 配列を解放 q->max = q->num = q->front = q->rear = 0; } } /*--- キューにデータをエンキュー ---*/ int QueueEnque(Queue *q, char *buffer) { if (q->num >= q->max) return (-1); /* キューは満杯 */ else { q->num++; strcpy(q->que[q->rear++] ,&buffer[0]); if (q->rear == q->max) q->rear = 0; return (0); } } /*--- キューからデータをデキュー ---*/ int QueueDeque(Queue *q, char *buffer) { if (q->num <= 0) /* キューは空 */ return (-1); else { q->num--; strcpy(&buffer[0],q->que[q->front++]); if (q->front == q->max) q->front = 0; return (0); } } /*--- キューの大きさ ---*/ int QueueSize(const Queue *q) { return (q->max); } /*--- キューに蓄えられているデータ数 ---*/ int QueueNo(const Queue *q) { return (q->num); } /*--- キューは空か ---*/ int QueueIsEmpty(const Queue *q) { return (q->num <= 0); } /*--- キューは満杯か ---*/ int QueueIsFull(const Queue *q) { return (q->num >= q->max); } int main(void) { int i=0,j=0,ret; char buffer[20]; FILE *fpin; Queue que; double ab,ac; char aa[10]; fpin=fopen("input2.txt","r"); //テキストファイルを読み取りモードで開く if (QueueAlloc(&que, 100) == -1) { puts("キューの確保に失敗しました。"); return (1); } while (1) { int m, x; printf("現在のデータ数:%d/%d\n", QueueNo(&que), QueueSize(&que)); printf("(1) エンキュー (2) デキュー (0) 終了:"); scanf("%d", &m); if (m == 0) break; switch (m) { case 1: if(fgets(&buffer[0],sizeof(buffer),fpin) ==NULL) { puts("もう読み込むデータがありません"); goto END; } printf("データ:%s",&buffer[0]); if (QueueEnque(&que, buffer) == -1) puts("データのエンキューに失敗しました。"); break; case 2: if (QueueDeque(&que, buffer) == -1) puts("デキューできません。"); else { printf("デキューしたデータは%d。\n", &buffer[0]); break; } } } END: QueueFree(&que); fclose(fpin); return (0); }

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

    下記を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です)

  • gccでコンパイル時のエラー

    // test.cpp #include <stdio> using namespace std; int main(int argc, char *argv[]) { printf("test\n"); return 0; } 上記コードをコンパイルしたいのですが make -k g++ -g -O2 -Wall -I. -c test.cpp -o test.obj test.cpp:2:17: stdio: No such file or directory test.cpp: In function `int main(int, char**)': test.cpp:7: error: `printf' was not declared in this scope test.cpp:7: warning: unused variable 'printf' make: *** [test.obj] Error 1 make: Target `all' not remade because of errors. となります。 #include <stdio> using namespace std; を #include <stdio.h> // using namespace std; にすれば正常に終了するのですがなぜでしょうか? gccはMingw5.1.6からインストールしたもので、 バージョンはgcc3.4.5です。 Meadow上から実行しました。 回答よろしくお願い致します。

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

専門家に質問してみよう