#include <iostream>
#include <vector>
#include <string>

using namespace std;

/*!
 *  食物連鎖モデル
 */
class Eater {
  vector<string> states_;

public:
  /*!
   * コンストラクタ
   */
  Eater( const char *name )
    { states_.push_back(name);  }

  /*!
   * 捕食
   */
  void eats( const Eater& eatee ) {
    int len;
    string bar, slack;

    if ( states_[0].length() < eatee.states_[0].length() ) {
      len = eatee.states_[0].length();
      bar = string( len - states_[0].length(), '-' );
    } else {
      len = states_[0].length();
      slack = string( len - eatee.states_[0].length(), ' ' );
    }

    states_[0] = '+' + states_[0] + bar + '+';

    for ( int i=0; i<eatee.states_.size(); ++i )
      states_.push_back( '|' + eatee.states_[i] + slack + '|' );

    states_.push_back( '+' + string( len, '-' ) + '+' );
  }

  /*!
   * 食べたものを表示
   */
  void ate() {
    for ( int i=0; i<states_.size(); ++i )
      cout << states_[i] << endl;
  }
};


/*!
 * 捕食を表す演算子
 */
Eater& operator | ( const Eater& lhs, Eater& rhs ) {
  rhs.eats( lhs );
  return rhs;
}

/*!
 * メイン
 */
int main( int ac, char **av, char **ev ) {

  Eater plankton("プランクトン");
  Eater waterFlea("みじんこ");
  Eater killifish("めだかの学校は川の中");
  Eater crucianCarp("フナ");
  Eater cat("ねこ");

  plankton | waterFlea | killifish | crucianCarp | cat;

  cat.ate();

  return 0;
}

