Как я могу написать собственное преобразование потока в 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 с потоковыми итераторами должен делать то, что вам нужно.