しかし、構造体のベクトルを持つ構造体で<<演算子を使用すると、コンパイルが失敗します。私は問題を紹介するために小さな例を作りました:
#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&))
| ^~~~~~~~
私は何が間違っているのですか?
では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]
コメントを追加