Как я могу написать собственное преобразование потока в C++?

Я изучаю C++ после того, как много работал с Haskell и функциональными языками в целом, и обнаружил, что постоянно пытаюсь решить одну и ту же проблему:

  • Читать некоторые данные из входного потока
  • Токенизируйте их на основе определенного алгоритма
  • Обрабатывать токены

Если бы это был Haskell, я мог бы просто воспользоваться тем фактом, что все лениво, и написать свое преобразование, когда я об этом думаю, и тогда оно будет применено по мере использования нижестоящего потока. Есть даже библиотеки, которые делают этот точный образец ( канал и трубы).

Допустим, я хотел взять последовательность 1 2 3 4 5 6 ... и вывод 12 34 56 ..., Я вижу, как написать специальный код, который работает с потоком и обрабатывает данные на месте. Но я хотел бы знать , существует ли механизм абстракции, который позволяет мне создавать новый поток путем преобразования данных (любым мыслимым способом) из другого потока. Эта абстракция должна позволять мне буферизовать данные в процессе их обработки, а не просто отображать отдельный элемент в новом значении.

Вот ограничения:

  • Я не могу использовать любую другую библиотеку, кроме stdlib.
  • Он должен работать на C++03 (что означает отсутствие функций C++11.)

Если вы думаете, это домашнее задание? Ну, вроде как, я получаю много назначений классов, которые требуют от меня работы с потоками данных (что является причиной отсутствия библиотек и ограничений C++03). Дело не в том, что я не знаю, как это сделать, используя while циклы, но я хотел бы знать, существует ли существующая потоковая абстракция в stl, просто ожидающая обнаружения и использования.

Но если единственный способ сделать это - использовать C++11, то я хотел бы знать.

2 ответа

Концептуальный код, не проверенный. Визуализация там много ошибок, проверка и правильный синтаксис.

struct add : public std::binary_function<int,int,int> {
  int operator() (int a, int b) {return (a + b);}
};

template<typename inType, typename dType, typename outType, class binFunc>
outType Transformer(inType& inStream, outType& outStream, binFunc func) {
  dType a, b;
  // Read some data from an input stream
  // Tokenize them based on a specific algorithm
  inStream>> a >> b; 
  //outStream << func(a, b);
  return func(a,b); // Process the tokens
}

int main() {
  std::ifstream in("input.dat", std::ifstream::in); // , std::ios::binary
  std::ofstream out("output.dat");
  struct add adder;  // to Process the tokens

  out << Transformer(in, out, adder);

  return exit_success;
}

Следующее не соответствует вашим потребностям без библиотечного решения (и у меня недостаточно репутации, чтобы оставить его в качестве комментария); Тем не менее, это будет полезно для вашего функционального мышления.

Дэвид Санкель (David Sankel) выступил с прекрасным докладом по FRP с использованием C++ на C++Now 2014. Он даже предоставил библиотеку, которую они используют для производства.

Видео можно найти здесь: https://www.youtube.com/watch?v=tyaYLGQSr4g&list=UU5e__RG9K3cHrPotPABnrwg

Слайды связаны с описанием видео и ссылками на github в конце слайдов.

Я подозреваю, что вы также получите вдохновение здесь: http://ericniebler.com/2013/11/07/input-iterators-vs-input-ranges/

std:: transform с потоковыми итераторами должен делать то, что вам нужно.

Другие вопросы по тегам