質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.78%

C++ vector配列<構造体>の中のvector配列への代入方法

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 12K+

score 995

追記2

std::vector::insert

iterator insert(const_iterator position, initializer_list<T> il); // (5) C++11
 // 挿入位置と初期化子リストを指定するバージョン
  {
    v.insert(v.begin() + 1, {"hhh", "iii"});
  }


コメント頂いた@yohhoyさん、@epistemeさん、ありがとうございます。

追記

boost::range::push_back(target, src);
boost::range::push_back
C++ extend a vector with another vector
@LouiS0616さんのコメントのリンクから検索などしていたら偶然見つけましたのでご参考までに。

解決!(勘違いでした)

初期化する時にまとめて代入出来ることと勘違いしていました。
結論:直接は出来ない が構造体のメンバ関数などを工夫すれば可能になる

回答くださった方ありがとうございました。

知りたいこと

下記サンプルコードのようなstd::vector<構造体>の中にあるstd::vector<int>への代入方法が知りたいです。
直感的に書いてみたコードだとエラーとなります。
data[0].vec.push_back({1,2,3});

VSCode上ではvecに赤い波下線でエラーが出ています

ご教示よろしくお願いします。

試したこと

data[0]::vec.push_back({1,2,3});
これもダメでした。

エラー

no instance of overloaded function "std::vector<_Tp, _Alloc>::push_back [with _Tp=int, _Alloc=std::allocator<int>]" matches the argument list -- argument types are: ({...}) -- object type is: std::vector<int, std::allocator<int>>
std::vector<int> Data::vec

サンプルコード

#include <bits/stdc++.h>

struct Data
{
    int id;
    std::vector<int> vec;
};

int main()
{
    std::vector<Data> data(10);

    data[0].id = 1;

//追記2
//コメントより
//既存vectorへの要素追加なら 
    data[0].vec.insert(data[0].vec.end(), {4,5,6}); //とも書けます。


    //※書き方が分からずここにエラーが出たままです
    data[0].vec.push_back({1,2,3});

    //こうすると当然問題無い
    data[0].vec.push_back(1);
    data[0].vec.push_back(2);
    data[0].vec.push_back(3);

    getchar();
    return 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

initializer_listを受け取るメンバ関数を用意してやれば良いかと。

#include <initializer_list>
#include <iostream>
#include <vector>

class Data {
private:
    int id_;
    std::vector<int> vec_;

public:
    Data(int id, const std::initializer_list<int>& lst)
        : id_(id), vec_(lst) {
    }
    friend std::ostream& operator<<(std::ostream&, const Data&);  
};

std::ostream& operator<<(std::ostream& out, const Data& data) {
    out << data.id_ << " {";
    for(auto elem: data.vec_) {
        out << elem << ", ";
    }
    out << "}";

    return out;
}

int main() {
    Data data{42, {1, 2, 3}};
    std::cout << data << "\n";
}

実行結果 Wandbox

42 {1, 2, 3, }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/15 12:17 編集

    boost::push_back(a, b); 
    イメージにピッタリなのはこれですね。
    boostではなくSTLに実装されたら完璧です。

    先程のコメントのリンクの中からキーワードで検索してみたところ、こういうのがあるらしいです。
    boost::range::push_back(target, src);
    https://greek0.net/boost-range/boost-range-push_back.html

    キャンセル

  • 2018/11/15 12:42

    boostに実装されているのだったら、C++標準でも採用されるチャンスがありそうですね。
    いつになるかはわかりませんが。

    キャンセル

  • 2018/11/15 23:20

    追記のとおりinsertで実現可能だったようですが、これはこれであると直感的ですよね。

    キャンセル

+2

こんなこともできるのかー程度の話と思って欲しいのですが、Boost.Assign的な方法もあります。
operator,(カンマ演算子)をオーバーロードして要素追加を簡潔にします。

#include <bits/stdc++.h>

struct Data
{
    int id;
    std::vector<int> vec;
};

template < class Container >
class AssignProxy{
    Container& container;
public:
    AssignProxy(Container& container): container(container) {}

    auto& operator,(typename Container::value_type const& val) {
        container.emplace_back(val);
        return *this;
    }
};

auto operator+=(std::vector<int>& vec, int val) {
    return AssignProxy{vec}, val;
}

int main()
{
    std::vector<Data> data(10);

    data[0].vec += 1, 2, 3;
    //          ^~~~~~~~~~~
    for(auto elem: data[0].vec) {
        std::cout << elem << " ";
    }
    return 0;
}

Wandboxで実行する

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/14 21:00

    回答ありがとうございます。
    そんなことまで出来てしまうのですね驚きです。

    キャンセル

+2

#include <iostream>
#include <vector>

struct Data
{
    int id;
    std::vector<int> vec;
};

int main()
{
    std::vector<Data> data(10);

    data[0].id = 1;

    // 追加じゃなく、代入なら...
    data[0].vec.assign({1,2,3});

    // できたかな?
    for ( int item : data[0].vec ) {
      std::cout << item << std::endl;
    }

    return 0;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/15 06:28

    回答ありがとうございます。
    ループで毎回追加したい時ではなく初回限定なら使えますね。

    assign()はあちこちで共通して使いたい配列がある時など外出し変数にして使いますね。

    キャンセル

  • 2018/11/15 21:55

    既存vectorへの要素追加なら data[0].vec.insert(data[0].vec.end(), {4,5,6}); とも書けます。

    キャンセル

  • 2018/11/15 22:02

    キャンセル

  • 2018/11/15 23:13

    コメントありがとうございます。
    vectorにもあったのですね。
    上記リンク先で確認しました。

    // 挿入位置と初期化子リストを指定するバージョン
    {
    v.insert(v.begin() + 1, {"hhh", "iii"});
    }

    キャンセル

checkベストアンサー

+1

data[0].vec.push_back({1,2,3});


push_backの使用方法を間違えています。
要素は一つずつ入れてやらなければなりません。

data[0].vec.push_back(1);
data[0].vec.push_back(2);
data[0].vec.push_back(3);


vecはvecter<int>型であるので、push_backの引数はint型である必要がある。
一方で{1,2,3}と配列を代入しようとしているため、型が違う、と怒られている状態です。


もうクローズしてしまいましたが、まだできないと断じるのは早いかと思います。

素のvectorは静的配列{...}の初期化子、代入演算子を持っています。
これと同じことを、構造体のコンストラクタなり代入演算子なりに宣言することで、一気に代入も可能なのではないかと思っています。

struct Data
{
    int id;
    std::vector<int> vec;

    Data(int i, const int v[]) : id(i), vec(v) {};
};


ただし、上記では const int * を受け取るコンストラクタが無いよ、とエラーになります。
どうやるのが正しいかな、むむむ。


C++11以上に限りますが、std::begin, std::endを使う方法が一番お望みのものに近いかも知れません。

#include <vector>
#include <iterator>

struct Data
{
    int id;
    std::vector<int> vec;

    Data(int i, int *b, int *e) : id(i), vec(b, e) {};
};

int main(void)
{
    int static_array[] = {1,2,3};
    struct Data d(1, std::begin(static_array), std::end(static_array));

    std::cout << d.vec[2] << std::endl;
    return 0;
}


一旦変数に代入しなければいけないのもイマイチですが、これくらいが限界かなと。

また、コンストラクタを経由する必要があります。
代入演算子では引数が1つしか取れない一方、vectorにはbeginとendの2つを渡す必要があるため。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/14 08:28

    コメントありがとうございます。
    質問編集と被りましたね^^;

    この方法は分かるのですが、初期化時に出来るような使い方ってありませんでしたっけ?

    キャンセル

  • 2018/11/14 08:37

    出来ないことをやろうとしていたわけですね^^;
    vector初期化時にまとめて代入出来ることと勘違いしてたみたいです。

    キャンセル

  • 2018/11/14 13:16

    追記ありがとうございます。
    実現可能かもしれませんが、素直に1つづつ入れることにしました。
    力不足で回答頂いた内容を理解するのはまだ難しいようです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る