1

<<オブジェクトに対してストリーム演算子 ( 、 )を定義できるようにしたいのです>>が、コンテキストに応じて異なるセットを使用できるように、複数のセットを用意したいと考えています。たとえば、次のようなオブジェクトがあるとします。

struct Foo {
  int a;
};

次に、いくつかの場所でこれを使用できるようにしたい

std::ostream& operator<<(std::ostream& out, const Foo& foo) {
  out<<foo.a;
}

そして他の人ではこれを使うことを好みます

std::ostream& operator<<(std::ostream& out, const Foo& foo) {
  out<<"'"<<foo.a<<"'";
}

しかし、これらの両方を同時に定義する方法がわかりません。

私は自分の回答を提出していますが、他の誰かが過去に私よりもこれを熟考する理由があり、できれば大規模なアプリケーションでそれを行うための組織的な方法を持っていることを願っています(したがって、「管理」という用語は質問のタイトル)。

4

3 に答える 3

4

マニピュレータを作成します。代替フォーマットに名前 (およびオーバーロード スロット) を与えるだけの単純なプロキシです。

// default format
std::ostream& operator<<(std::ostream& out, const Foo& foo) {
  return out<<foo.a;
}

// custom format

// helper class
struct print_quoted_manip {
    Foo const &ref;

    print_quoted_manip( Foo const &in )
        : ref( in ) {}
};

// implementation
std::ostream& operator<<( std::ostream& out, print_quoted_manip o )
    { return out << '\'' << o.ref << '\''; }

// the manipulator
print_quoted_manip print_quoted( Foo const &in )
    { return print_quoted_manip( in ); }

// usage
std::cout << print_quoted( my_foo );

これを簡単にテンプレート化して、あらゆるタイプのオブジェクトを引用符で囲むことができます。

于 2013-05-02T11:07:45.573 に答える
2

提案されたソリューションは機能しますが、実行しないことを強くお勧めします。演算子のオーバーロードは、悪用されやすい強力なツールです。行動が直感的で明白でない場合、多くの場合、良いことよりも悪いことになります。

代わりに、最初のバージョンを使用することをお勧めします

std::ostream& operator<<(std::ostream& out, const Foo& foo) {
  out<<foo.a;
}

そして単に使用する

cout << "'" << fooObject << "'";

別のオーバーロードを提供する代わりに。

これにより、コードが明確で直感的になり、デバッグが容易になります。

コード内での の不適切な使用に起因する多数のバグが想像できusing namespaceます。bコードの重複もあります。オブジェクトに別のメンバーを追加して、そのメンバーを出力したい場合はどうでしょう。他の誰かがオーバーロードの 1 つを見つけ、それを変更し、最初の外観で動作することを確認し、他のオーバーロードを忘れる可能性があります。

于 2013-05-02T10:03:13.767 に答える
1

適切な名前の演算子の各セットの周りに名前空間を宣言し、それらの特定のストリーム演算子を使用する必要がある関数内でその名前空間を使用できます。例えば:

#include <iostream>
#include <string>

struct Foo {
  int a;
};

namespace raw_output {
  std::ostream& operator<<(std::ostream& out, const Foo& foo) {
      out<<foo.a;
  }
}

namespace quoted_output {
  std::ostream& operator<<(std::ostream& out, const Foo& foo) {
      out<<"'"<<foo.a<<"'";
  }
}

void do_raw() {
  using namespace raw_output;
  Foo f = { 7 };
  std::cout<<f<<std::endl;
}

void do_quoted() {
  using namespace quoted_output;
  Foo f = { 7 };
  std::cout<<f<<std::endl;
}

void do_raw_and_quoted() {
  Foo f = { 7 };
  { // Anonymous scoping to use different ops in the same function scope
    using namespace raw_output;
    std::cout<<f<<std::endl;
  }
  {
    using namespace quoted_output;
    std::cout<<f<<std::endl;
  }
}

int main() {
  do_raw();
  do_quoted();
  do_raw_and_quoted();
}

このアプローチでは、最上位 (関数スコープ外) で名前空間を使用しないようにする必要があります。

于 2013-05-02T09:51:43.203 に答える