<<演算子のオーバーロード:構造体のベクトルを使用した構造体

luxderfux
  • ベクトルの<<のオーバーロードは機能します。
  • カスタム構造体の<<のオーバーロードは機能します。
  • 組み合わせも同様に機能します。

しかし、構造体のベクトルを持つ構造体で<<演算子を使用する、コンパイルが失敗します。私は問題を紹介するために小さな例を作りました:

#include <iostream>
#include <ostream>
#include <vector>

template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& v) {
    out << "[";
    for (auto it = v.begin(); it != v.end(); ++it) {
        out << *it;
        if (std::next(it) != v.end()) {
            out << ", ";
        }
    }
    out << "]";
    return out;
}

namespace xyz {

struct Item {
    int a;
    int b;
};

struct Aggregation {
    std::vector<Item> items; 
};

std::ostream& operator<<(std::ostream& out, const Item& item) {
    out << "Item(" << "a = " << item.a << ", " << "b = " << item.b << ")";
    return out;
}

std::ostream& operator<<(std::ostream& out, const Aggregation& agg) {
    out << "Aggregation(" << "items = " << agg.items << ")";
    return out;
}

}  // namespace xyz

int main() {
    xyz::Aggregation agg;
    agg.items.emplace_back(xyz::Item{1, 2});
    agg.items.emplace_back(xyz::Item{3, 4});

    std::cout << agg.items << std::endl;  // works: [Item(a = 1, b = 2), Item(a = 3, b = 4)]
    std::cout << agg << std::endl;        // fails, expected: Aggregation(items = [Item(a = 1, b = 2), Item(a = 3, b = 4))
}

コンパイラエクスプローラへのリンク:https//godbolt.org/z/a8dccf

<source>: In function 'std::ostream& xyz::operator<<(std::ostream&, const xyz::Aggregation&)':
<source>:35:41: error: no match for 'operator<<' (operand types are 'std::basic_ostream<char>' and 'const std::vector<xyz::Item>')
   35 |     out << "Aggregation(" << "items = " << agg.items << ")";
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~ ~~~~~~~~~
      |                           |                    |
      |                           |                    const std::vector<xyz::Item>
      |                           std::basic_ostream<char>
In file included from /opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/iostream:39,
                 from <source>:1:
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/ostream:108:7: note: candidate: 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]'
  108 |       operator<<(__ostream_type& (*__pf)(__ostream_type&))
      |       ^~~~~~~~

私は何が間違っているのですか?

cigien

ではmain機能、あなたはこの行を記述する場合:

std::cout << agg.items << std::endl;

コンパイラは、のすべてのオーバーロードについてグローバル名前空間を検索しますoperator<<過負荷解決によって正しい過負荷が選択されるため、呼び出しは機能します。

ここに同様のコードを書くと

std::ostream& operator<<(std::ostream& out, const Aggregation& agg) {
    out << "Aggregation(" << "items = " << agg.items << ")";
    return out;
}

このコードは名前空間xyzにあるため、コンパイラは最初operator<<に名前空間ののオーバーロードを検索しますxyzオーバーロードが見つかると、追加のオーバーロードの検索を停止します。ただし、operator<<必要な実際の名前空間がないためxyz、過負荷の解決に失敗し、エラーが発生します。

これを修正するにはoperator<<vector<T>名前空間にテイクを移動するだけxyzです。

これがデモです。


あなたが実際にしたい場合はoperator<<とるvectorグローバルスコープと同様に、ネームスペースからアクセスできるように、あらゆるタイプのをxyzあなたは、あなたの質問に行ったように、あなたはグローバルスコープでそれを定義することができます。次に、演算子をxyz、またはできれxyzば、次のように、名前空間内の必要な特定の関数に移動します。

namespace xyz 
{
  // using ::operator<<;  // if you want all of `xyz` to see the global overload
 
  std::ostream& operator<<(std::ostream& out, const Aggregation& agg) 
  {
    using ::operator<<;  // if you only want the global overload to be visible in this function
    out << "Aggregation(" << "items = " << agg.items << ")";
    return out;
  }

  // ...
}

ここだデモショーはどのようにストリーミングすることvector<int>と同様にvector<xyz::Item>


using名前空間全体を汚染するのではなく宣言を必要な関数に対してローカルにすることができることを指摘してくれた@NathanPiersonに感謝しますxyz

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

マップを使用した構造体のostream演算子のオーバーロード

分類Dev

構造体の演算子のオーバーロード

分類Dev

非型テンプレート構造体のメンバー構造体のコピー代入演算子をオーバーロードします

分類Dev

テンプレート構造体のオーバーロード演算子

分類Dev

構造体演算子のオーバーロードを宣言する場所

分類Dev

C ++の古い構造体演算子のオーバーロード構文が変更されましたか?

分類Dev

C構造体をオーバーロードする演算子

分類Dev

テンプレート呼び出し演算子と汎用ラムダを使用した構造体のオーバーロード-gccvs clang

分類Dev

std :: coutは、構造体のオーバーロードされた '<<'演算子では機能しません

分類Dev

テンプレート化された構造体の<<演算子をオーバーライドする

分類Dev

別の構造体内の構造体の演算子のオーバーロードはエラーを引き起こします

分類Dev

構造体の二項<<演算子をオーバーライドする

分類Dev

マップキーとしてのc ++構造体と演算子のオーバーロード

分類Dev

構造体/クラスラッパーのC ++オーバーロード自動演算子

分類Dev

どのように適切にCでのセットでの使用を可能にする構造体で<演算子をオーバーロードする++

分類Dev

C ++ 11-構造体のベクトル内の構造体のメンバーを変更する

分類Dev

Cのポインタを使用した構造体のバブルソート

分類Dev

プライベートモジュールタイプを使用した構造体メンバーの定義

分類Dev

リフレクトを使用して構造体内の構造体フィールドにアクセスする

分類Dev

構造体のベクトルを構造体メンバーのベクトルに仮想的に変換します

分類Dev

構造体のドット演算子

分類Dev

構造体のベクトルのグローバルベクトルに要素を追加する

分類Dev

構造体のベクトルを2回ソートする

分類Dev

(。)または→演算子を使用したCの構造体

分類Dev

オーバーロードされた構造体演算子で定数パラメーターを使用できますか?

分類Dev

back_inserterを使用して構造体の単一メンバーからベクトルを作成する

分類Dev

構造体のベクトルから特定のメンバーのベクトルを取得します

分類Dev

構造体のC ++オーバーロードoperator()

分類Dev

ポインターとオフセットを使用して構造体のメンバーのベクトルを反復処理するパート2

Related 関連記事

  1. 1

    マップを使用した構造体のostream演算子のオーバーロード

  2. 2

    構造体の演算子のオーバーロード

  3. 3

    非型テンプレート構造体のメンバー構造体のコピー代入演算子をオーバーロードします

  4. 4

    テンプレート構造体のオーバーロード演算子

  5. 5

    構造体演算子のオーバーロードを宣言する場所

  6. 6

    C ++の古い構造体演算子のオーバーロード構文が変更されましたか?

  7. 7

    C構造体をオーバーロードする演算子

  8. 8

    テンプレート呼び出し演算子と汎用ラムダを使用した構造体のオーバーロード-gccvs clang

  9. 9

    std :: coutは、構造体のオーバーロードされた '<<'演算子では機能しません

  10. 10

    テンプレート化された構造体の<<演算子をオーバーライドする

  11. 11

    別の構造体内の構造体の演算子のオーバーロードはエラーを引き起こします

  12. 12

    構造体の二項<<演算子をオーバーライドする

  13. 13

    マップキーとしてのc ++構造体と演算子のオーバーロード

  14. 14

    構造体/クラスラッパーのC ++オーバーロード自動演算子

  15. 15

    どのように適切にCでのセットでの使用を可能にする構造体で<演算子をオーバーロードする++

  16. 16

    C ++ 11-構造体のベクトル内の構造体のメンバーを変更する

  17. 17

    Cのポインタを使用した構造体のバブルソート

  18. 18

    プライベートモジュールタイプを使用した構造体メンバーの定義

  19. 19

    リフレクトを使用して構造体内の構造体フィールドにアクセスする

  20. 20

    構造体のベクトルを構造体メンバーのベクトルに仮想的に変換します

  21. 21

    構造体のドット演算子

  22. 22

    構造体のベクトルのグローバルベクトルに要素を追加する

  23. 23

    構造体のベクトルを2回ソートする

  24. 24

    (。)または→演算子を使用したCの構造体

  25. 25

    オーバーロードされた構造体演算子で定数パラメーターを使用できますか?

  26. 26

    back_inserterを使用して構造体の単一メンバーからベクトルを作成する

  27. 27

    構造体のベクトルから特定のメンバーのベクトルを取得します

  28. 28

    構造体のC ++オーバーロードoperator()

  29. 29

    ポインターとオフセットを使用して構造体のメンバーのベクトルを反復処理するパート2

ホットタグ

アーカイブ