Centaur
01:04 23-06-2004 [C++] Expect
Как хочется иногда написать:
stream << "(" << x << ", " << y << ")";

А потом зачитать обратно:
stream >> "("  >> x >> ", " >> y >> ")";

А низззя. Изволь прочитать символ, сравнить с '(', не равно — бросить exception. Равно — читай дальше.

Или можно?

class expect
{
public:
  explicit expect(const std::string& text) : text_(text) {}

  class exception : std::runtime_error
  {
  public:
    explicit exception(const std::string& message) : std::runtime_error(message) {}
  };

  friend std::istream& operator>>(std::istream& stream, const expect& value)
  {
    std::istream::sentry s(stream);
    if (!s)
    {
      stream.setstate(std::ios::failbit);
      return stream;
    }

    for (std::string::const_iterator i = value.text_.begin(), e = value.text_.end(); i != e; ++i)
    {
       char c;

       stream.get(c);
       if (!stream || c != *i)
       {
         throw expect::exception("Expected: " + value.text_);
       }
    }
    return stream;
  }
private:
  const std::string& text_;
};

stream >> expect("(") >> x >> expect(", ") >> y >> expect(")");

Обобщение до произвольных std::basic_stream<Char, Traits> и std::basic_string<Char, Traits, Allocator> оставляется читателю в качестве упражнения
Комментарии:
Maxtradamus
01:28 23-06-2004
а не проще использовать регулярные выражения?
Centaur
09:46 23-06-2004
Да, и писать не на C++, а на Perl’е. Или подключить boost::regex. Или boost::spirit.

Только это дополнительные зависимости, и тащить за собой boost ради такой мелочи — неохота.
Xirax
12:33 23-06-2004
Ух-ты, в этой записи я даже кое-что понял
Anafay
12:12 24-06-2004
На подобном принципе построены народные развлечения для облегчения читаемости кода в стиле:

result_set:=query
               .prepare_from(storage1)
               .where(agent {TYPE_NAME}.condition1)
               .and_then(agent condition2(?))
            .union
               .prepare_from(storage2)
               .where(agent condition3(?,once "123"))
            .end_query


Правда, почему-то не везде такое приживается, и приходится разгребаться с длинным и малопонятным кодом , хотя и оверхед незначителен, и работы лишней немного, потом все при сопроводении многократно окупится...
Centaur
15:24 29-07-2004
На самом деле здесь есть overhead. При вызове
stream >> expect("(")

произойдёт сначала неявный вызов конструктора std::string, который скопирует строчку. Для промышленного использования надо переписать это с использованием const char* вместо std::string.