Два глупых вопроса по STL.

Serab

Во-первых, почему ostream::write принимает char*, а не void*? Кастить парит.
Во-вторых, как можно при помощи алгоритма copy вывести set<int> в бинарный файл (в бинарном же виде)?

Maurog

Во-первых, почему ostream::write принимает char*, а не void*? Кастить парит.
немного ошибаешься
// 27.6.2.6 Unformatted output:
basic_ostream<charT,traits>& put(char_type c);
basic_ostream<charT,traits>& write(const char_type* s, streamsize n);
я думаю, это все объясняет
Во-вторых, как можно при помощи алгоритма copy вывести set<int> в бинарный файл (в бинарном же виде)?
поподробнее плиз опиши задачу. что вы ожидаете от этого вывода? будете ли вы читать потом это?

olega

Во-вторых, как можно при помощи алгоритма copy вывести set<int> в бинарный файл (в бинарном же виде)?
Вам не должно этого хотеться так.

oliver11

Во-вторых, как можно при помощи алгоритма copy вывести set<int> в бинарный файл (в бинарном же виде)?
Свой output iterator написать. Можно посмотреть на ostream_iterator и сделать по образу и подобию.

Maurog

Свой output iterator написать. Можно посмотреть на ostream_iterator и сделать по образу и подобию.
итераторы вроде не занимаются форматированием вывода. этим заведуют всякие facet, ctype, traits, etc
в общем, тоже не считаю это хорошей затеей
лучше освойте сериализацию другими методами

oliver11

итераторы вроде не занимаются форматированием вывода.
Если в итератор можно засунуть вызов write то почему бы так и не сделать? Полностью же по аналогии с back_insert_iterator и ostream_iterator будет.
этим заведуют всякие facet, ctype, traits, etc
Как с помощью всего этого решить задачу вывода последовательности в двоичном виде в ofstream через std::copy?

Serab

итераторы вроде не занимаются форматированием вывода. этим заведуют всякие facet, ctype, traits, etc
Ну естественно, итераторы этим не занимаются, они итерируют :) Но вот ostream_iterator пользуется <<, хочется воспользоваться вместо него .write'ом. Хотелось стандартного решения, свой итератор написать — более-менее решение, а вот хотелось знать, как без лишней писанины.

Serab

я думаю, это все объясняет
ну мооожет быть, но все равно, write'ом, кмк, чаще выводят raw data, чем отформатированный заранее текст. Ну да пох.

okunek

как без лишней писанины.
Не тот язык выбрал :grin:

Serab

я не против пописать там, где это нужно, но здесь вот форматированный вывод можно сделать, а бинарный — на первый взгляд нет.

olega

Короче гугли по словам c++ ser1al1zat10n, увидишь, какие кактусы вырастают на почве невинных желаний типа твоего из первого п0ста.
---
Ч0рт0вb1 теHдepы на г0C3аkyпкN съеJIи M0CK :mad:

Serab

Фишка в том, что мне не надо сериализовать set, мне надо сохранить числа из него подряд в файл, там формат фиксирован внешними факторами.

olega

Я бы написала библиотечкку для работы с файлами этого формата, и юзал бы её.

Serab

да я бы тоже написала, но слишком обобщенную ее писать лень (а по задаче придется). Да и не в этом дело, просто до этого не так много опыта с STL'ем было, вот и ищу правильные пути.

olega

> да я бы тоже написала, но слишком обобщенную ее писать лень (а по задаче придется). Да и не в этом дело, просто до этого не так много опыта с STL'ем было, вот и ищу правильные пути.
> STL'ем ... правильные пути
> пути
"
В пути я занемог.
И все бежит, кружит мой сон
По выжженным полям.
"

"
Сказали мне, что эта дорога меня приведёт к океану смерти,
И я с полпути повернула вспять.
С тех пор все тянутся предо мною кривые, глухие окольные тропы…
"

pitrik2

Во-первых, почему ostream::write принимает char*, а не void*? Кастить парит.
а что такое void*?
указатель? зачем указатель выводить в поток?
char* - это бинарные данные, их в поток и надо выводить
ещё лучше если бы это называлось byte*, тогда бы таких вопросов не было бы
почему void* не бинарные данные?
ну хотя бы потому что sizeof(void) не определён

pitrik2

Фишка в том, что мне не надо сериализовать set, мне надо сохранить числа из него подряд в файл, там формат фиксирован внешними факторами.
зачем тебе при этом std::copy?

Serab

Потому что в форматированном виде я могу вывести (через ostream_iterator почему я не должен хотеть сделать это в бинарном виде?

Serab

а что такое void*?
указатель? зачем указатель выводить в поток?
йоу, мэн! Ты чего? Указатель указывает на данные, которые мне надо записать в поток. void* — это указатель на что угодно, см. функцию memcpy, например.
char* - это бинарные данные, их в поток и надо выводить
ещё лучше если бы это называлось byte*, тогда бы таких вопросов не было бы.
почему void* не бинарные данные?
ну хотя бы потому что sizeof(void) не определён
Да char и byte и так в голове синонимы (для c/c++ так что это неважно, но вот это про sizeof(void) — что-то неясное.
Это все не похоже на идеологическую причину, скорее это артефакт дизайна, потому что в том же C все-таки принято (хотя может и не всеми) указатель на сырые данные представлять в виде void*. См. memcpy, MPI_Send и др.

Dasar

>Это все не похоже на идеологическую причину, скорее это артефакт дизайна, потому что в том же C все-таки принято (хотя может и не всеми) указатель на сырые данные представлять в виде void*. См. memcpy, MPI_Send и др.
в C - есть понятие "сырые данные" и активно используется
а в C++ - считается, что "сырые данные" - это зло, и стараются это понятие не использовать

istran

На stackoverflow нашел идею достаточно лаконичного решения:

#include <iostream>
#include <iterator>
#include <sstream>
#include <set>
#include <algorithm>
#include <cstdlib>


template<class T>
struct serialize
{
serialize(const T & i_value = T : value(i_value) {}
operator T const {
return value;
}
T value;
};

template<class T>
std::ostream& operator <<(std::ostream &os, const serialize<T>& obj)
{
os.writechar*)&obj.value, sizeof(T;
return os;
}

template<class T>
std::istream& operator >>(std::istream &is, serialize<T> & obj)
{
is.readchar*)&obj.value, sizeof(T;
return is;
}

int main {
std::set<int> s, s1;
generate_n(std::inserter(s, s.end 20, std::rand);
std::stringstream ios;
typedef std::ostream_iterator< serialize<int> > OutputIterator;
typedef std::istream_iterator< serialize<int> > InputIterator;

std::copy(s.begin s.end OutputIterator(ios;
std::copy(InputIterator(ios InputIterator std::inserter(s1, s1.end;
if (s == s1) {
std::cout << "OK" << std::endl;
} else {
std::cout << "Fail" << std::endl;
}
return 0 ;
}

Serab

Это было предложено уже здесь. Но спасибо за возможность увидеть объем.
Я в итоге закопировал в вектор, а его потом заврайтил в один вызов. Там не более 50-ти элементов, так что пох.
Оставить комментарий
Имя или ник:
Комментарий: