Сергей Холодилов ([info]fat_crocodile) wrote,
@ 2008-10-24 07:52:00
Previous Entry  Add to memories!  Tell a Friend  Next Entry
Entry tags:c++, программинг, статьи

HOWTO: Свой поток ввода-вывода, beta-1
Коллеги, я опять написал статью и мне опять нужна ваша помощь.

Кто ещё С++ помнит, прочитайте пожалуйста. Статья не маленькая, но вроде простая как две копейки. Про то, как коварным наследованием подчинить себе iostream и использовать его в своих гнусных целях.

HOWTO: Свой поток ввода-вывода

Статья ещё не опубликована, так что просьба не выносить ссылку далеко. Давайте считать, что у неё TTL=2. И не забывайте вычитать.

Отзывы нужны любые, от "ничего не понял, ужасно" до "всё понял, ужасно" через "ну, типа, нормально, чё говорить-то". Я автор мнительный, в себе не уверенный, в собственной нормальности сомневающийся, сторонние подтверждения мне важны.

Более-менее осознанно я сам смогу читать статью только где-то через неделю, сейчас я ещё в горячке, так что ни один здоровый человек этого пока не читал.

Upd: Возможно, не совсем понятно, что я хотел. Все знают высказывание "дай человеку рыбу - накормишь его сегодня, дай ему удочку - накормишь на всю жизнь"? Мне мало даже этого, я хочу научить делать удочки.

Если рыба это конкретный код, удочка - знания, позволяющие написать такой код, то я хотел показать, откуда эти знания берутся. В результате статья это не задача-решение, а задача-процесс поиска решения.

Конечно, можно было бы всю первую часть заменить словами "basic_istream использует класс basic_streambuf в качестве источника данных". И какая разница, откуда я это знаю, может мне это приснилось, или ко мне было откровение, явился ангел с трубой и т.п.... Ну вот как-то хотелось попробовать другую форму подачи информации.

Upd2: Чуть-чуть обновил, лежит там же. Второй раз читать смысла нет. Изменения:
- примечание к _Read_s (где-то тут)
- совет после basic_buffered_istreambuf (чуть вверх отсюда)
- последний эпиграф стал менее прямолинейным :)

Upd3: Окончательно обнаглел. Добавил в начало абзац:

Конечно, я уже знаю «правильный ответ», и мог бы объяснить его как-нибудь короче, понятнее и систематичнее… Но мне кажется более интересным провести вас тем же путём, которым шёл я сам, по сторонам открываются потрясающие виды. Следуйте за мной.

Ай да я, ай да Пушкин. Делать вид, что я пишу технические статьи с каждым разом всё труднее.

Upd4: Удивительно, но народ не жалуется. Хм. Тем временем, следующее обновление. Из заметного:
- поменялся конец раздела про обобщённые символы, теперь там немного больше полезной информации.
- мне объяснили, откуда взялось имя eback, я описал это в статье.




(45 comments) - (Post a new comment)


[info]kodt_rsdn
2008-10-24 05:37 am UTC (link)
Так, на всякий случай - я давным-давно на RSDN написал цикл "Hello debug window", где как раз показывал, как кустомизировать стримы.

(Reply to this) (Thread)


[info]fat_crocodile
2008-10-24 10:02 am UTC (link)
Т.е. боян? Чорт.

А, вот, нашёл http://www.rsdn.ru/Forum/message/461141.flat.aspx
Это не совсем то, у меня гораздо длиннее :)

Во-первых, я про чтение написал (istream), оно в данном случае сложнее.
Во-вторых, я делаю вид, что учу учиться ловить рыбу.

(Reply to this) (Parent)


[info]cormagh_oreilly
2008-10-24 05:58 am UTC (link)
По части порождения данных имхо понятно написано.

Возможно офф, но когда я пытался для работы с сетью применить std::istream/std::ostream, столкнулся с проблемой network byte order.

Т.е. допустим у нас есть

some_network_ostream ostrm;
u16_t u16 = 0x0102;
u32_t u32 = 0x01020304;
ostrm << u16 << u32;

И хотелось бы, чтоб при помещении в поток автоматически вызвались бы htons / htonl.

Ни в одном из материалов, которые я нашел, данная тема не была раскрыта.

Если я правильно понял, то проблема в том, что для STL'ного потока каждое вхождение int_type равнозначно, а мне требуется различная обработка в зависимости от размера читаемых данных. Вот только как этого добиться?

(Reply to this) (Thread)


[info]fat_crocodile
2008-10-24 10:11 am UTC (link)
Спасибо :)

Нет проблема не в этом. Если бы всё было равнозначно, то всегда передавалось бы 4 байта. А количество же правильное получается? Как добиться - переопределить операторы << для типов.

int_type он для другого используется. Это "расширенный" символ. Проблема обычного символа в том, что у него все значения допустимы, невозможно взять и выбрать одно из них eof-ом. Поэтому eof-ом выбрано (int_type)-1. А char_type сначала преобразуется к unsigned, а потом к int_type, в результате и любого char_type отрицательное число не получится.

(Reply to this) (Parent)


[info]fat_crocodile
2008-10-24 10:18 am UTC (link)
Хотя, при использовании стандартных << он бы по идее вообще передавался текстом, в виде десятичного числа.

(Reply to this) (Parent)(Thread)


[info]cormagh_oreilly
2008-10-24 12:41 pm UTC (link)
Сегодня еще поэкспериментировал - да, так и выводится.

Я тогда в итоге написал свой велосипед, который как надо сериализует примитивные типы, строки и массивы (в соответствии с описанием протокола) в буфер. А дальше уже этот буфер проталкивал send'у.

(Reply to this) (Parent)


[info]ran_dom
2008-10-24 10:53 am UTC (link)
Серёжа - тебе самому всё это показалось удобным?
и ты сфокусировался на реализации с прицелом на многообразие контейнеров (помимо файлов) - а многообразие данных ты затронул поверхностно. например, я не нашел ничего про сериализацию объектов

PS: "Через буферы к звёздам" можно заменить на "Через буферА к звёздам" - учитывая последнюю главку...

(Reply to this) (Thread)


[info]fat_crocodile
2008-10-24 11:39 am UTC (link)
Мне это было скорее нужно, чем удобно...

Одна библиотека прасинга xml принимает на вход именно istream. Это ужасно, на мой взгляд, правильно было бы определить свои интерфейс с одной функцией read. Зато пришлось разобраться. Выбрать другую библиотеку не хотелось, т.к. всем остальным эта меня устраивала.

Многообразие данных обеспечивает istream и его стандартные операторы. И нестандартные операторы >>, которые пользователь определяет для своих объектов. Это положительная часть iostream: достаточно строго отделён источник данных от инструментов форматирования.

(Reply to this) (Parent)(Thread)


[info]ran_dom
2008-10-24 11:46 am UTC (link)
а что за библиотека? когда не подходит NSXML я использую tinyXML - хватает...

про сериализацию - я не просил её описывать - это большая тема. но упомянуть, думаю, стоит - что и такое бывает, и бывает удобно

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-24 11:54 am UTC (link)
Poco. Она хороша тем, что это не только xml, но и ещё куча всего. Нам были нужны логи и базы данных. Я даже написал для них модуль работы с MySQL: http://pocoproject.org/poco/blog/?p=131

Ну и P в названии от слова Portable, она вполне соответствует. На нашем проекте использовалась в Windows, Linux, FreeBSD.

Ну, я подразумевал, что человек, который хочет свой поток сделать уже знает, как используются потоки. Иначе и смысла нет.

(Reply to this) (Parent)(Thread)


[info]ran_dom
2008-10-29 01:28 pm UTC (link)
посмотрел описание библиотеки и её исходники. описание понравилось, исходники не очень. я пока не понял, они странные по необходимости или...

скажи, а ты знаешь, почему вы пользуетесь именно этой библиотекой?
я попробовал сравнить с http://www.ncbi.nlm.nih.gov/books/bv.fcgi?rid=toolkit.TOC.full - там всё совсем страшно ;). есть ли другие библиотеки с похожими намерениями?

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-29 01:40 pm UTC (link)
Знаю, это при мне было. Это первая, которую нашли и которая нас устроила. Началось всё с перехода на 64-разрядные системы, по ходу выяснилось, что на них плохо работает mysql++. Я уже не помню, что именно плохо, вроде страдала поддержка 64-разрядных же целых.

Так что сначала были нужны базы данных. Потом мы начали использовать их sax-парсер xml и логи.

Библиотека привлекла тем, что:
- она поддерживается и развивается
- у неё аккуратный код
- она свободная
- она переносимая.
- есть сразу всё, что нам было нужно.

(Reply to this) (Parent)(Thread)


[info]ran_dom
2008-10-29 01:46 pm UTC (link)
те альтернативные либы ты не знаешь? я сейчас делаю сравнение разных библиотек, пригодных к нашим проектам - надеялся часть пути пройти по вашим следам;)

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-29 01:51 pm UTC (link)
Нет, всё подряд подробно не смотрели, это было довольно быстрое решение. Если бы по ходу возникли проблемы, поискали бы. Ну, проблемы, конечно, возникли, но всё решилось. Правда, теперь наша версия в одном месте не совместима с их :)

Подключайтесь к Поко :) Передавай при случае Алексу от меня привет :)

(Reply to this) (Parent)(Thread)


[info]ran_dom
2008-10-29 01:59 pm UTC (link)
в основном меня всё устраивает. сейчас студент пишет на ней сервер для бродкаста видео - получится, так буду рекомендовать другим...

а какого Алекса ты имеешь в виду?

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-29 02:07 pm UTC (link)
Alex Fabijanic :)

Один из главных разработчиков, самый активный из них. Мы с ним много общались, когда они включали наш код в свой проект.

(Reply to this) (Parent)


[info]ran_dom
2008-10-29 01:50 pm UTC (link)
скажи, а зачем тогда ты писал коннектор для MySQL? или первоначальный вас не устраивал?

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-29 01:55 pm UTC (link)
Его просто не было. Был Access, Oracle, Postgre кажется...

MySQL не поддерживался, но у них раздёлён общий интерфейс к БД и интерфейс к конкретной БД, последние можно дописывать.

Это не заняло много времени.

(Reply to this) (Parent)(Thread)


[info]ran_dom
2008-10-29 02:01 pm UTC (link)
хихи - сейчас MySQL упоминается на основной странице загрузки исходников

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-29 02:04 pm UTC (link)
Ещё бы. Не поддерживать MySQL - это была их большая ошибка, очень популярная база, не смотря ни на что.

(Reply to this) (Parent)(Thread)


[info]ran_dom
2008-10-29 02:07 pm UTC (link)
несмотря ни на ЧТО?
я с ним не работал - какие у него плюсы-минусы?

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-29 02:18 pm UTC (link)
У меня во френдах есть такой странный человек [info]plumqqz. Он работает в mial.ru и занимается большими БД профессионально. И очень ругает MySQL. А хорошая база по его мнению одна - Оракл :)

Из того, с чем столкнулись - большую нагрузку держит с трудом. Но это действительно _большая_ нагрузка. Когда с 100 серверов одновременно пишут в одну таблицу, оно дохнет. Пришлось применять извращённые искуственные приёмы: разбили таблицу на 512 штук, нужная выбирается как модуль от деления id хоста на 512. Плохо, что это приходится делать вручную.

Можно и не вручную, там есть секционирование, но тогда без транзакций :) Или то или то :)

Вообще, специалист по БД разнёсёт её в пух и прах, можешь пообщаться с кем-нибудь, я то так, мимо проходил... Но, насколько я понимаю, это значит только что она не выжмет из железа 100%, выжмет около 10%.

(Reply to this) (Parent)


[info]fat_crocodile
2008-10-29 01:41 pm UTC (link)
А что странного в исходниках?

(Reply to this) (Parent)(Thread)


[info]ran_dom
2008-10-29 01:43 pm UTC (link)
меня раздражают файлы, состоящие из тривиальных функций:
int GetValue() { return my_object.GetValue(); }
и так весь файл. тут что-то с проектированием не так, если такие макароны требуются...

(Reply to this) (Parent)


[info]fat_crocodile
2008-10-24 11:42 am UTC (link)
Я в самом начале написал:

Библиотека ввода-вывода языка С++ – достаточно спорное явление. Но, так или иначе, она существует, иногда используется, и надо как-то с этим жить.

Т.е. вопросов о том, насколько это удобно и хорошо я не касаюсь, я довольно скептично отношусь к iostream. Но иногда бывает нужно.

(Reply to this) (Parent)


[info]scavenger_spb
2008-10-24 09:00 pm UTC (link)
Я немного покритикую... специально не читал каменты, а сразу за перо взялся... так что не обессудь. Начну сначала.
- Тема для меня неожиданная. Скорее всего я мало работал со стандартными потоками (да и с другими потоками тоже), но у меня ни разу не возникало желания их менять или писать свои.
- "Типичные сценарии работы с потоком – порождение и преобразование." Ну, какие же они типичные??? Типичные - это чтение и запись в поток. Возьми любую программу и посчитай количество операторов << и >>, и любых других функций потоков. Наверняка первых на порядок, а скорее всего на несколько будет больше.
- "Генеалогия". Я бы нарисовал UMLные квардратики вместо унылых названий классов и наследований. Это наглядней. А описаний к этому практически нет. Плюс, я бы не стал упоминать _Iosb вообще, ибо это особенность реализации и на нее полагаться не стоит. А стоит полагаться на ios_base, который описан в стандарте. (Еще на всякий случай упомяну, что идентификаторы, начинающиеся с _ и заглавной буквы зарезервированы за разработчиками компиляторов. И это использовать не стоит, т.к. разработчики могут это поменять безо всяких предупреждений и будут по-своему правы.)
- "Обобщённые символы". char_traits я бы так не переводил. Скорее это свойства символов. В первую очередь они предназначены для строковых операций. А т.к. в потоках последние встречаются достаточно часто, то они встречаются и здесь. И вместо переопределения свойств символов для флоата, я бы сделал акцент на необходимости их поддержки в своем классе (хотя бы в размере двух стандартных вариантов).
- "Источник данных", "Источник данных II". Если бы я захотел посмотреть реализацию у Микрософта, то открыл бы их исходники. Смотреть на "избранные" части этих исходников в статье мне не интересно. Вместо того, чтобы писать о том, как это сделано, лучше бы написал, что там сделано и зачем. Это было бы полезней. Все равно реализацию ты не поправишь. Разве только, если ручками подправишь исходники. (Что тож иногда приходится делать. Где-то натыкался на сообщение о том, что в потоках в 2005 студии без пака что-то течет.)

Что касается секьюрности, то секьюрность тут в том, что конец строки обозначается не спец символом, которого может и не быть, а всегда задается более-менее точно. Что позволяет недопустить переполнение буфера. Да, это усложняет пользование, но зато заставляет задуматься об этом. К тому же это "мелкое" расширение от Микрософта, и в свете потенциальной многоплатформенности я бы про это вообще бы не упоминал, или упомянул бы во вставке.

- "Простое чтение, обработчики". Я так и не понял откуда и зачем взялся класс basic_symbol_istreambuf. Точнее я понял, что это пример... но какого его предназначение, как класса осталось для меня загадкой. Непонятно, зачем мы его вообще создаем и чем не устраивает стандартный поток. Я бы сначала описал цели, которые преследуются созданием этого класса, а потом бы уже на основе этих целей переопределял бы методы. А так получается, что мы пишем код только ради того, чтобы хоть что-нить написать.

Вотъ. Теперь буду читать остальные каменты. Звиняй, если повторил сказанное выше, - хотел избежать тлетворного влияния ;)

(Reply to this) (Thread)


[info]fat_crocodile
2008-10-25 12:31 am UTC (link)
>> "Типичные сценарии работы с потоком – порождение и преобразование." Ну, какие же они типичные???

Не, это ты смотришь на C++. Проблема в том, что в C++ нет удобных механизмов для этого, поэтому и не используется. Ну, разве то, что я описываю - это удобно? Скорее, ущербно. Но и этого мало кто умеет.

Если посмотреть шире, то операции с потоками данных - основа программирования на shelle в unix. Практически всё строится вокруг этого, получается очень элегантно и лаконично. Например, мой предыдущий пост :)

>> "Генеалогия". Я бы нарисовал UMLные квардратики вместо унылых названий классов и наследований. Это наглядней.

Это было бы нагляднее, если бы была не простая линейная структура, а что-то более интересное. Не вижу ничего унылого :) ios_base, basic_ios - это же полёт фантазии :)

Кроме того код точнее квадратиков.

>> А описаний к этому практически нет.

Это намеренно. Целью было показать, что за istream стоит довольно внушительный бекграунд. Подробное описание этого бекграунда - не задача статьи, да и многовато его, но обозначить надо.

>> Плюс, я бы не стал упоминать _Iosb вообще, ибо это особенность реализации и на нее полагаться не стоит.

Да большая часть кода, который я привёл - особенность реализации, и на неё полагаться не стоит. У меня и не было задачи писать только то, на что можно полагаться... Задача в самом начале статьи описана: есть куча кода и надо понять, как это работает. Это невозможно делать по абстрактному коду в вакууме, нужно взять конкретную реализацию. В ней будет что-то частное, но будет и что-то общее, общее нужно выделить, а частное можно иметь ввиду...

Про _Большая Буква знаю, только я иначе интерпретировал это правило. Мне кажется, имеется ввиду, что в любой момент разработчики могут ввести такие имена в любой области видимости. Поэтому самим такие имена использовать не стоит, т.к. будут перекрываться и ничего хорошего.

>> "Обобщённые символы". char_traits я бы так не переводил.

Нее. Обобщённый символ это тип. А char_traits это "пачка методов" :)

>> на необходимости их поддержки в своем классе (хотя бы в размере двух стандартных вариантов)

Ммм... Это звучит разумно.
Хотя слово "необходимость" тут явно лишнее.

>> Если бы я захотел посмотреть реализацию у Микрософта, то открыл бы их исходники. Смотреть на "избранные" части этих исходников в статье мне не интересно. Вместо того, чтобы писать о том, как это сделано, лучше бы написал, что там сделано и зачем. Это было бы полезней.

Это было бы вреднее :)
Это не научная, это инженерная статья, её задача - обратный инженеренг stl для получения ответа на данный конкретный вопрос. На примере версии MS. Я смотрел STLPort, там, знаешь, не лучше.

Поэтому писать "что сделано" не вижу смысла, мне проще показать. А, главное, если я показываю, то каждый может очень просто убедиться в моей правоте. Читателю практически не нужно мне верить, это большой плюс.

А писать "зачем сделано" не в моей компетенции. Не я проектировал stl. И уж потоки - точно не я. Я бы это сделал сильно иначе, скорее всего.

>> Все равно реализацию ты не поправишь.

Я и не собирался, я её изучаю а не правлю.
На самом деле, кроме исходников и стандарта информации на эту тему немного.
И одно другое очень дополняет.

(Reply to this) (Parent)(Thread)


[info]scavenger_spb
2008-10-25 08:33 pm UTC (link)
Много мы понаписали... по поводу написанного в статье. А теперь я хочу еще сказать по поводу ненаписанного... ;)

Как я понял, ты хотел написать гайд по реализации собственного класса потока. Мне кажется, что это не удалось. Т.к. я так и не понял, какие методы в каком случае мне надо для этого переопределять, т.е. я в любом случае полезу в документацию. У тебя нигде нет списка функций, которые надо переопределять, т.е. он есть, но он размазан по тексту, перемежается кодом твоего класса и жуткими вставками из СТЛя.

Вместо этой мешанины мне бы хотелось увидеть список методов, которые можно переопределить, а также причины, по которым это стоит делать, как-то структурировать их, чтобы понять, что мне надо переопределить при реализации потока для работы с архивным потоком (о котором ты писал ниже), например. Ну, и ниже отдельно по каждому методу описать его контракт. Т.е. что он должен делать и какие правила для него есть (типа того, как правильно работать с буфером), в общем-то почти то, что у тебя сейчас есть.

Еще я не нашел, какую задачу решает твой поток. Из-за этого я также не понял, чем твоя реализация потока лучше стандартной и почему стандартная тебя не устраивает.

(Reply to this) (Parent)(Thread)


[info]scavenger_spb
2008-10-25 08:43 pm UTC (link)
Почитал статью еще раз... оказываеццо, со вчерашнего дня все поменялось в лучшую сторону, но часть камента все еще в силе.

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-25 10:53 pm UTC (link)
:)

Посмотри в посте, я там описал, что поменялось :)

(Reply to this) (Parent)(Thread)


[info]scavenger_spb
2008-10-26 12:01 pm UTC (link)
Угумс... я и свежую версию посмотрел. Есть пара замечаний по поводу новой фразы про задачу:

- Непонятна постановка этой задачи. Вроде как ответ - это пара классов для упрощенного переопределения потока. Но это ответ в какой задаче? Для решения каких задач созданы твои классы?
- Твое решение задачи, конечно, интересно посмотреть, но оно мало поможет при решении собственной задачи, т.к. ты никак не обозначил места, на которые надо обратить особое внимание, где и на основе чего надо выбирать ту или иную реализацию функций. Единственное, что есть, - это пара вспомогательных классов, которые можно использовать.

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-27 07:25 am UTC (link)
Пара классов это слишком частный ответ. Это "рыба". Нормальный ответ это объяснение, как оно работает. Ну и пара классов, как пример практического применения. Это "удочка" :)

Для каких целей - для того чтобы сделать определение своих потоков простым и приятным. Наследуешься и переопределяешь одну логичную функцию.

"Решение" в данном случае - как "процесс решения" - это поиск в коде MS смысла, выстраивание его так, чтобы смысл проявлялся, становился очевидным.

(Reply to this) (Parent)


[info]fat_crocodile
2008-10-25 11:17 pm UTC (link)
Гайд - хорошее слово. В варианте перевода "проводник, гид; экскурсовод" :) В данном случае я выступаю в роли гида и провожу небольшую экскурсию по stl. Экскурсия имеет узкую тему и выстроенную последовательность экспонатов. Вот скелет Чапаева в 10 лет. А вот - в 15. Обращаю внимание на логику развития. Видите, в 10 лет он сломал руку, вот, на 15-тилетнем скелете тоже видно место, где срослись кости. И на всех последующих тоже.

Кстати, по итогам, функцию нужно переопределить ровно одну :) underflow. Но контракт у неё не очень прозрачный, помимо входных-выходных параметров она должна правильно управлять внутренним состоянием родительского класса. Я бы не стал такое проектировать, честно говоря. Хотя получилось неплохо.

Мой поток генерирует строчку случайных чисел :) Стандартные такого не умеют.

(Reply to this) (Parent)(Thread)


[info]scavenger_spb
2008-10-25 11:26 pm UTC (link)
Если нужно переопределить только одну функцию, то зачем тогда делать еще один класс? Почему сразу нельзя ее переопределить? Какие цели преследовались при написании твоего класса? В каких случаях он подходит?

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-25 11:33 pm UTC (link)
Именно потому что у неё противоестественный контракт.

Мой класс оставляет потомкам ровно одну простую и понятную функцию:

// Возвращает либо количество прочитанного, либо -1
virtual int readData(char_type* buffer, size_t length) = 0;

или другую, но тоже простую и понятную:

// Возвращает либо traits_type::eof(), либо traits_type::to_int_type(c)
virtual int_type readChar() = 0;

В зависимости от того, какой именно "мой класс" используется (там два варианта).

(Reply to this) (Parent)


[info]scavenger_spb
2008-10-25 09:03 pm UTC (link)
А можно я еще немного поумничаю?

> Если посмотреть шире, то операции с потоками данных - основа программирования на shelle в unix.

Угумс... ключевое слово на шелле. Шелл организует потоки данных, а не работает с ними напрямую. Напрямую с ними работают конкретные программы, написанные иногда и на плюсах. Или ты думаешь, что в sed'е чаще используется создание потоков, чем операции ввода и вывода в них? А в данном случае мы обсуждаем потоки в языке, на котором пишутся программы, обрабатывающие данные. Разные уровни - разные представления об объектах, ну и все такое...

> Про _Большая Буква знаю, только я иначе интерпретировал это правило...

Ну, использовать у себя такие идентификаторы точно не стоит :) хотя бы потому, что они просто плохо читабельны. Кроме того, это еще означает, что это может быть не портируемо на другие платформы со всеми вытекающими. По идее должно быть достаточно методов, указанных в стандарте.

Кроме того есть еще пара мелочей по поводу STL'я... стандарт не всегда требует наличия функций с конкретной сигнатурой. Так функция с одним параметром может быть реализована, как функция с двумя параметрами, второй из которых имеет значение по-умолчанию. Кроме того стандарт не всегда требует определение конкретной функции именно в конкретном классе, а всего лишь ее доступности в последнем, что и происходит с функциями в basic_ios - ios_base.

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-25 10:33 pm UTC (link)
Можно :)

А почему на C++ нельзя решать похожие задачи? Ну, т.е. понятно, что можно всё писать на шелле, но иногда несколько неудобно. Если же мне в C++ надо разархивировать xml, распарсить его, получить выжимку, а потом заархивировать её, зашифровать и направить по http (по ходу добавив где надо заголовки и преобразовав в base64), почему мне не сделать это в духе работы с потоками?

Про стандарт интересно. А как отличить, где он чего он требует? Можешь конкретно это место там посмотреть? Вроде там всё однозначно, просто приведён интерфейс классов basic_ios и ios_base.. Но я стандарт первый раз в жизни стал читать, многих тонкостей могу не улавливать.

(Reply to this) (Parent)(Thread)


[info]scavenger_spb
2008-10-25 10:46 pm UTC (link)
Парсинг xml я не стал бы реализовывать в виде стандартного потока. Но даже и в случае использования стандартного потока, основная работа с потоками будет вестись в выжимке. И тут уж без чтения/записи в потоке не обойдется.

А стандарт... не поверишь... ни разу не читал :) Все больше левые книжки/статьи. Про такие фишки я тоже где-то вычитал.
С basic_ios и ios_base все просто - в реализации от Микрософт присутствуют все необходимые методы. :) Все остальное отдается на откуп производителям компиляторов.

(Reply to this) (Parent)(Thread)


[info]fat_crocodile
2008-10-25 10:52 pm UTC (link)
Парсинг работает иначе, важно что парсер принимает на вход стандартный поток. Который я формирую из потока данных из файла, на который вешаю поток разорхиватора. А потом выжимка пишется в другой стандартный поток... А он прозрачно направляется в архиватор, в шифровалку, в http и в конце в сокет. И всё это потоки.

С тем, что реализация MS работает я не спорю. Я просто не уверен, что производитель компилятора может произвольно переносить методы в базовый класс.

(Reply to this) (Parent)(Thread)


[info]scavenger_spb
2008-10-26 11:52 am UTC (link)
> Я просто не уверен, что производитель компилятора может произвольно переносить методы в базовый класс.

Почитал стандарт... нашел такие пункты:

17.3.1.2 Requirements
3 Interface convention requirements are stated as generally as possible. Instead of stating "class X has to define a member function operator++()," the interface requires "for any object x of class X, ++x is defined." That is, whether the operator is a member is unspecified.

---

17.4.4.4 Member functions
2 An implementation can declare additional non-virtual member function signatures within a class:

  • by adding arguments with default values to a member function signature; The same latitude does not extend to the implementation of virtual or global functions, however.
  • by replacing a member function signature with default values by two or more member function signa tures with equivalent behavior;
  • by adding a member function signature for a member function name.
---

17.4.4.7 Derived classes

1 It is unspecified whether a class in the C++ Standard Library is itself derived from other classes (with names reserved to the implementation).


Вроде это как раз покрывает то, о чем я писал ;)

(Reply to this) (Parent)


[info]fat_crocodile
2008-10-25 11:00 pm UTC (link)
Это, кстати, классический случай стековой архитектуры. Любимая тобой (и мной тоже, конечно, без этого никуда) инкапсуляция в полный рост :)

(Reply to this) (Parent)

Очень короткие комменты в этом ЖЖ...
[info]fat_crocodile
2008-10-25 12:32 am UTC (link)

>> Что касается секьюрности, то секьюрность тут в том, что конец строки обозначается не спец символом, которого может и не быть, а всегда задается более-менее точно.

Гы :) Паша, почитай текст :) Этой функции на вход передаётся два размера. Один обозначает размер строчки куда читать, второй - размер запрашиваемых данных. Как ты думаешь, что она делает? Правильно, она выбирает минимальный из двух и использует его :) Я не вижу причин, почему этого не может сделать вызывающий код, если ему всё равно известен размер буфера (чтобы его передать в _s функцию).

Точнее, это лучшее, что она могла бы делать. Но если ты заглянешь в streambuf, то увидишь, что даже этого она не делает. Размер строки используется только в одном месте, а должен бы хотя бы в двух. Это в VS2005, 2008-й у меня просто нет.

>> "Простое чтение, обработчики". Я так и не понял откуда и зачем взялся класс basic_symbol_istreambuf. Точнее я понял, что это пример... но какого его предназначение, как класса осталось для меня загадкой.

Такое же как у basic_streambuf. Этот класс упрощает создание своих "источников данных" для потоков. Теперь достаточно унаследоваться от него и переопределить одну единственную функцию с интуитивно понятной семантикой.










(Reply to this) (Parent)


[info]fat_crocodile
2008-10-25 12:42 am UTC (link)
Да, и спасибо за подробный отзыв!

И по поводу менять и писать свои. Очень удобно архивировать/читать из архива. Это то, с чем лично сталкивался. Причём, поскольку интерфейс тот же - istream - те, кто пишут/читают не в курсе, куда/откуда они это делают. В частности так наш парсер xml обрабатывает файлы типа file.xml.gz

(Reply to this) (Parent)


[info]koshka_na_krysh
2008-10-29 04:41 pm UTC (link)
Привет! Френдится буш?

(Reply to this) (Thread)


[info]fat_crocodile
2008-10-29 06:20 pm UTC (link)
Done

(Reply to this) (Parent)


(45 comments) - (Post a new comment)

Create an Account
Forgot your login or password?
Login w/ OpenID
English • Español • Deutsch • Русский…