幼稚園時代「何組」でしたか?

構造体vectorの入れ子のfillの使い方

vectorデータのメモリを確保する関数をテンプレート関数で作ったのですが、構造体の入れ子vectorのデータの時、ビルドが通りません。
構造体や入れ子vectorの時のfillの使い方が間違っているようですが、理由がわかりません。直し方を教えて下さい!

ソースコード
-------------------------------------------------------------
#include <vector>
using namespace std;

struct aa{
 float x; float y;
 aa& operator = (const aa& rhs)
 {
  if (this == &rhs) return *this;
  x = rhs.x; y = rhs.y;
  return *this;
 };
};

template<typename T1, typename T2> bool getM(
  vector<T1>& vDat, const T2 datN )
{
 bool bRet = true;
 try{
  vDat.resize( datN );
 }catch( bad_alloc ){
  return false;
 }
 fill( vDat.begin(), vDat.end(), 0x0 );
 return bRet;
}

template bool getM<aa, int> ( vector<aa>& vDat, const int datN );
template bool getM<vector<aa>, int> ( vector< vector<aa> >& vDat, const int datN );

int main()
{
 vector< vector<aa> > data;
 data.clear();
 if( false == getM( data, 10 ) )return -1;
 for( int i = 0; i < 10; i++ ){
  if( false == getM( data.at(i), 20 ) )return -1;
  for( int j = 0; j < 20; j++ ){
   data.at(i).at(j).x = 1.;
   data.at(i).at(j).y = 1.;
  }
 }
 return 0;
}

エラーメッセージ
-------------------------------------------------------------
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
main.cpp:
エラー E2285 c:\Borland\Bcc55\include\algorith.cc 519: 'aa::operator =(const int
)' に一致するものが見つからない(関数 fill<aa *,int>(aa *,aa *,const int &) )
警告 W8057 c:\Borland\Bcc55\include\algorith.cc 520: パラメータ 'value' は一度も
使用されない(関数 fill<aa *,int>(aa *,aa *,const int &) )
エラー E2285 c:\Borland\Bcc55\include\algorith.cc 519: 'vector<aa,allocator<aa>
>::operator =(const int)' に一致するものが見つからない(関数 fill<vector<aa,alloc
ator<aa> > *,int>(vector<aa,allocator<aa> > *,vector<aa,allocator<aa> > *,const
int &) )
警告 W8057 c:\Borland\Bcc55\include\algorith.cc 520: パラメータ 'value' は一度も
使用されない(関数 fill<vector<aa,allocator<aa> > *,int>(vector<aa,allocator<aa>
> *,vector<aa,allocator<aa> > *,const int &) )
*** 2 errors in Compile ***

A 回答 (6件)

こんにちは。



以下、的外れな内容でしたらすみません。

データの初期化が目的なら、構造体 (クラス)のコンストラクタで、メンバデータを
初期化するのは如何でしょうか?

以下は構造体(クラス)定義の一例です。

=================================
//class aa {    //←個人的にはclassで定義する方が好み。
struct aa {
public:        //←下記メンバをクラス外からアクセスするにはpublicで宣言
  float x;      //メンバデータ(1)
  float y;      //メンバデータ(2)
public:
  aa(){ x=0.11; y=0.22; }    //←コンストラクタでメンバを初期化
                   //※今回は初期化されたのを確かめるため、
                   //ここでは 0 でない値を設定しています。
  aa& operator=(const aa& rhs)  //演算子(=)のオーバーロード
  {
    if (this == &rhs) return *this;
    x = rhs.x;
    y = rhs.y;
    return *this;
  }
};
=================================

上記の定義を用いて、ご提示のソースを変更したソースを下記に掲載しました。
宜しければ検証してみて下さい。
※当ソースでは、データ表示の際の行数を少なくするため、配列の要素数を
減らしています。
※当方では、「Borland C++ 5.5.1」及び、「MinGWのgcc(g++) 3.4.5」で検証
してみました。

■変更版ソース(下記リンク先参照)
http://ideone.com/Zfmpt

以上です。
    • good
    • 0
この回答へのお礼

こんばんは。大変ご丁寧なご回答、どうもありがとうございます。No.1の方へのお礼で書いた operator = の定義が、気持ち悪いなと思っていたのですが、ご教示いただいたようにコンストラクタで初期化すればよいのですね!構造体もこんなことができるとは、ぼんやりと知っていましたが、実際に使ったことはありませんでした。とても勉強になりました。これなら、構造体や入れ子の場合は、fillを使わなくてもいいですね。ご教示いただいた、美しいコードで、もっと勉強します。どうもありがとうございました。

お礼日時:2010/08/05 23:21

わざわざ fill を使わなくても, resize だけで (大きくした部分は) 「デフォルトの初期化」をしてくれるんじゃなかった

っけ....
    • good
    • 0
この回答へのお礼

お礼が大変遅くなり、申し訳ありませんでした。ご回答どうもありがとうございます。
ご回答の内容は、初めて知りました。ソースを見ると、デフォルトコンストラクタがあることが要求されているようです…。参考になりました。

お礼日時:2010/08/08 21:32

一言で言うと現状のgetMでは「右辺が数値型の演算子=を許す型によるdeque/list/vector、もしくはその派生クラス」以外はコンパイルを通せません。


std::fillの第3パラメータ、即ち0x0はどうあがいても数値型でしかないので「要素に数値型を代入可能、もしくは右辺値がintである演算子=を定義済」でなければならないためです。
#3でも言われてますが、このstd::fillは本当に必要ですか?

deque/list/vector以外のSTLがアウトである理由は他のSTLにはresize()がないこと。もっともこちらはvector前提ならそう問題ではないでしょう。
    • good
    • 0
この回答へのお礼

再度のご登場、どうもありがとうございます。fillでなくても少ないステップ数で初期化ができればなんでもよいのですが…。恥ずかしながら、0x0はただの数値であることをあまり認識していませんでした。入れ子無しの基本データ型のvectorなら、いつもfillで初期化していました。(宣言と同時にデータ個数がわかっていれば、vector<int> data(10,0); などとしています)
まだ、vector以外のコンテナはあまり使った経験がないのですが、resize()が使えないものもあることは、勉強になります。今回に限れば、vector専用関数なので、問題はないかと思います。

お礼日時:2010/08/05 23:13

単に 0x0 と書けば, それは当然 int です. だから


> fill( vDat.begin(), vDat.end(), 0x0 );
> の「0x0」がint扱いされている
のはあたりまえ.
でどうすればいいかだけど, それはあなたがここで何をしたいかによる. そもそも fill しないとダメなの?
    • good
    • 0
この回答へのお礼

再度のご登場、どうもありがとうございます。なかなか身につかず、0x0がintだということをうっかり忘れていました。fillの目的は初期化です。今回、vector用のメモリ確保関数を作ったのも、要素が数万~数十万ものvectorデータが多用されているからです。ほとんどのvectorデータは入れ子無しの基本データ型なので、メモリ確保→初期化を一連の動作でやっていました。

お礼日時:2010/08/05 23:07

std::fill()があるという事はalgorithmもインクルードしてるはずですが、それはさておき。



std::vector<std::vector<int>> a;

という型のオブジェクトaを考えた時に、さてa[0]の型は何でしょうか?
そこに整数型は代入できますか?

という事です。
    • good
    • 0
この回答へのお礼

ご回答、ありがとうございます。ご指摘通り、algorithmもインクルードしていました。投稿の際に、はしょりすぎました。すみません。
ご回答の意味するところをしばらく考えないと理解できない低レベルですが、入れ子vectorに代入する初期値は、例だとstd::vector<int>型の何かでないといけないのですね。
具体的には、どうするんでしょう?困りました!!
でも、入れ子vectorって、一番内側(ここではvector<int>)だけ初期化すればいいような気がしてきました。外側は要素数だけ指定してやれるけど、実体(内側)はまだないんですもんね。私の考え、間違ってましたら、すみませんがご指摘お願いします。

お礼日時:2010/08/04 21:18

理由はちゃんとエラーメッセージに書いてありますが....

    • good
    • 0
この回答へのお礼

ご回答、どうもありがとうございます。

>> 理由はちゃんとエラーメッセージに書いてありますが....

はい、おっしゃる通りです…(^_^;

'aa::operator =(const int)' に一致するものが見つからない(関数 fill<aa *,int>(aa *,aa *,const int &) )
'vector<aa,allocator<aa>>::operator =(const int)' に一致するものが見つからない(関数 fill<vector<aa,allocator<aa> > *,int>(vector<aa,allocator<aa> > *,vector<aa,allocator<aa> > *,const int &) )

よくよく考えてみると、
fill( vDat.begin(), vDat.end(), 0x0 );
の「0x0」がint扱いされているってことなんでしょうか。
とすると、構造体のoperator()オーバーロードは、以下のような感じでよろしいんでしょうか?

aa& operator = (const int& rhs)
{
x = rhs; y = rhs;
return *this;
};

引数型と戻り値型が違うのがなんだか気持ち悪いです。
vector<aa,allocator<aa>>::operator =(const int)
の方は、どう書けばよいか、サッパリわかりません…。aaの定義中には書けなさそうなのですが??

お礼日時:2010/08/04 21:09

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!