dポイントプレゼントキャンペーン実施中!

enum enumBType {
 EN_A = 0,
 EN_B,
 EN_O,
 EN_AB,
};

struct person_t {
 long lNumber;
 enumBType bType;
 int age;
 int zipCode;
};

int main() {
 person_t personAry[10] = {
  { 123456, EN_A, 20, 5300001 } ,
  { 123457, EN_B, 19, 5300050 } ,
  { 123458, EN_B, 22, 4000010 } ,
  { 123459, EN_O, 30, 6310001 } ,
  { 123460, EN_AB, 18, 7300123 } ,
   : // 省略
 };

// ※1 構造体person_t型の配列personAryをvectorに変換
 std::vector<person_t> vPerson( ※1 );
 // std::vector<person_t> vPerson( personAry[0], personAry[10-1] ); NGだった

// ※2 構造体person_tのある要素が存在するかを調べたい
 std::vector<person_t> it = std::find( vPerson.begin(), vPerson.end() , 123458 );
 if ( it != vPerson.end() ) {
  printf("find! \n");
 }
}

// C++11

上記サンプルソースにて、2点質問があります。
※1
構造体配列をvectorに変換はできない?いちいちpush_backするしかないんでしょか?
※2
アルゴリズムのfind等を使おうとする場合、構造体にoperatorを作らなきゃ駄目?
(確かに何のキーで検索するのか見えないので要るような気がしますが、イマイチわかりません)

C#やVBばっかり触っててC++のテンプレートクラスやら何やらが全然解っていません。
これこれ、こうだよ と分かる方いましたらご教示ねがいます。

A 回答 (5件)

※1


C++11 なら std::begin とか std::end を使って
std::vector<person_t> vPerson(std::begin(personAry), std::end(personAry));
でできないかな? まあ, 今の場合そもそも配列作らんでもいいよなって話だけど.

※2
std::find には述語を取るバージョンがある. 但し返り値の型に注意 (面倒くさければこの場合 auto で OK だが).
    • good
    • 0
この回答へのお礼

なるほど既存配列のコンテナからイテレータ出せば良かったのかな、と理解しました
std::begin()自体今知ったとこですが。

2についても大体分かりました。
複雑な条件下であれば関数オブジェクトやっぱoperator作るのが一番分かりやすそうです。select from~ってクエリみたくできねぇかな、と必死こいて考えていましたが・・・

一応2について以下の2種類の方法で出来るというのを確認したので
今後この質問を参照する人の為にもここに記載させてもらいます。

// 関数オブジェクト(ワンライナーで済ます)
long lvalue = 123457;
enumBType evalue = EN_B;

// auto it = ~でも良い
std::vector<person_t>::iterator it = find_if(vPerson.begin(), vPerson.end(), [](person_t &t) { return ( (t.lNumber == lvalue) ); } );

// 関数オブジェクト
struct myNumber {
 long _number;
 myNumber( const long& _l) {
  _number =_l;
 }

 bool operator() (const person_t& patt) const {
  return ( _number == patt.lNumber );
 }
};

std::vector<person_t>::iterator it2 = find_if(vPerson.begin(), vPerson.end(), myNumber(123460) );

// 単純なoperator作っとく
struct person_t {
 long lNumber;
 enumBType bType;
 int age;
 long zipCode;

 operator long() {
  return lNumber;
 }
};
std::vector<person_t>::iterator itr = find(vPerson.begin(), vPerson.end(), 123460 );

まぁ速い遅い考えるともっとしっかり作るべきですが。

お礼日時:2015/09/29 02:15

御意>#4. 忘れてました.



個人的には [lvalue] としたいところ.
    • good
    • 0

[](person_t &t) { return t.lNumber == lvalue; }


は、[&]とかにしないと駄目じゃないかな。
    • good
    • 0
この回答へのお礼

[=]だとエラーになりますね。具体的にコピーするような使用例も思いつかず
大体参照だけの[]ないし[&]くらいしか使わんだろう、みたいな勝手な想像があります。
このあたりは私の勉強不足もあるので、また詰まったら質問させてください。

お礼日時:2015/10/01 01:24

補足だけ.



まずラムダを使うなら引数は
[](const person_t &t) { return ( (t.lNumber == lvalue) ); }
のように const を付けておく方が親切. ところでこの括弧はなんのためにあるんだろう.

それから関数オブジェクトでいくなら (当然このクラスにしか使わないだろうから) person_t のネストクラスとして作る方がいいと思う (myNumber って名前もどうだろうか) し, 変換演算子も
operator long() const { /* ... */ }
のように const を付けた方がいいと思う.
    • good
    • 0
この回答へのお礼

>のように const を付けておく方が親切. ところでこの括弧はなんのためにあるんだろう.
long lvalue = 123457;
enumBType evalue = EN_B;

( (t.lNumber == lvalue) && (t.bType == evalue) ) のようにしようかな、として質問内容と齟齬ができてしまうので
消した後の残骸です。

その他、まぁ名前は適当なので置いといてください。
myNumberどころかenumなのにbTypeってなんだよプリフィクスおかしいだろとかなっちゃうので

お礼日時:2015/10/01 01:16

*1


personAry[0] は、personAry[0]の場所ではなく、その構造体そのものが「値」となっています。
personAry[10-1] も、personAry[10-1]の場所ではなく、その構造体そのものです。

それに対して、std::vector(開始,終了)形式のコンストラクタで求められているのは「開始の場所(イテレータやポインタ)」と「終了の場所」です。

C#やVBを知っているのなら。
C++では、structもclassも「値型」です。「参照型」ではありません。
「参照型」に相当するのはポインタです。


*2
person_t は構造体で、 123458 は 整数です。
型がまったくちがう(doubleとintのような暗黙の変換も存在しない)ので「同じ」になるわけがありません。

例えるなら
並んでいる自動車を指差して、「あの中から、リンゴと同じ自動車を探してきてください」と言うようなものです。

このあたりはC#やVBでも同じでは?


> テンプレート

最近のC#,VBには「ジェネリクス型」というのがあるかと思います。
対応させるなら、あれです。
    • good
    • 0

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