я только начинаю изучать С++, поэтому позникают вопросы правильности применения тех или иных методов...
задача такая:
есть несколько типов данный. под типом (в данном контексте) подразумеваю родной тип С++ (или stl) плюс тип форматирования (выравнивать влево/вправо, значащие нули/нет и т.д..).
также у каждого элемента кроме типа есть размер, т.е. его фиксированная длинна в буффере. (я еще не выбрал как удобнее будет работать через буффер или поток. поток вроде как логичнее, но могут быть проблеммы с итераторами. только об этом потом...)
теперь хотелось бы ф-цию форматирования (а возможно и просто копирования в буффер) вынести в сообветствующих класс форматирования. для этого можно реализовать соответствующую ф-цию:
class C
{
public:
typedef std::string value_type;
static void write(const std::ostream &os,
const value_type &value, int length) {};
};
и вызывать соответственно:
base_item_type::write(){T::write(...)}
только что-то мне это не нравится...
не то static не нравится, не то еще что-то... вроде как предчувствия в проектировании...
да и вообще хотелось бы inline...
ладно, перейдем ко второй части...
теперь хотелось бы поиметь сооветствующий класс со списком таких элементов. (именованным списком).
что-то типа:
class file_001
{
item_type::C item1(10);
item_type::D item2(2);
...
}
вот тут то я и передумал насчет потоков...
захотелось (посмотрев auto_value из "Исходников") сделать автоматическое создание, плюс вычисление сдвига относительно начала буффера...
тогда двигаясь по списку (класс file_001 это элемент списка) мы можем легко читать/писать любой элемент (лучше даже назвать поле item1, item2 ...)
прийдя к такому выводу решил что можно конвертировать буффер на лету и позвращая
const value при чтении ну и перекрыть оператор =.
таким образом
value_type m_value;
не совсем уместно...
что думают знатоки по этому поводу? не сильно ли я навернул? может есть подобные примеры на посмотреть?
PS время не поджимает, так что пока экспериментировать могу вволю...
PSS были еще варианты с виртуальными методами read/write, но мне не понравилось...
такое я и на Delphi с пол-пинка напишу... поскольку учусь — хотелось бы на template. но если Вы считаете что так разумней — хотелось бы это услышать.
PSSS для самих классов собираюсь написать codegen... просто сами структуры уже есть в xml. под Delphi писал с генератором и виртуальными методами...
Здравствуйте, Oleg A. Bachin, Вы писали:
OAB>я только начинаю изучать С++, поэтому позникают вопросы правильности применения тех или иных методов...
OAB>задача такая: OAB>есть несколько типов данный. под типом (в данном контексте) подразумеваю родной тип С++ (или stl) плюс тип форматирования (выравнивать влево/вправо, значащие нули/нет и т.д..).
OAB>также у каждого элемента кроме типа есть размер, т.е. его фиксированная длинна в буффере. (я еще не выбрал как удобнее будет работать через буффер или поток. поток вроде как логичнее, но могут быть проблеммы с итераторами. только об этом потом...)
Через поток — проще. Есть strstream, который выводит в строку.
Мне решение видится так:
template<class Data, class Fmt>
struct apply_fmt
{
Data data; // пока что обойдемся без операторов приведения типа, как в auto_value.
};
template<class Data, class Fmt>
ostream& operator<< (ostream& ost, apply_fmt<Data,Fmt> const& v)
{
return ostream << Fmt() << v.data;
}
Fmt — классы, экземпляры которых выводятся как команды для ostream.
Поскольку команды известны на стадии проектирования, то все детали запихаем
Здравствуйте, Кодт, Вы писали:
К>Через поток — проще. Есть strstream, который выводит в строку.
вероятно я не достаточно четко в конце описал почему через буффер удобнее (IMHO)...
и сразу (забегая вперед)... под именнованным списком понималась именно структура!
для чего?
чтобы можно было сделать так:
class A
{
item_fmt<N> id(5);
item_fmt<C> first_name(50);
}
my_vector<A> vecA;
std::cout << vecA.current.first_name;
vecA.current.id = 1234;
К>Мне решение видится так: К>
К>template<class Data, class Fmt>
К>struct apply_fmt
К>{
К> Data data; // пока что обойдемся без операторов приведения типа, как в auto_value.
К>};
эээ... эт конечно хорошо, но во второй части уклон был сделан именно на динамические чтение/запись в буффер.
т.е. непосредственное "value_type m_value" в классе не присутствует...
К>template<class Data, class Fmt>
К>ostream& operator<< (ostream& ost, apply_fmt<Data,Fmt> const& v)
К>{
К> return ostream << Fmt() << v.data;
К>}
К>
К>Fmt — классы, экземпляры которых выводятся как команды для ostream. К>Поскольку команды известны на стадии проектирования, то все детали запихаем К>[c] К>// отдельные команды
или я не понимаю, или будет создаваться экземпляр токо для вывода в поток, а потом разрушаться...
К>template<int w> struct fmt_setw {};
К>template<int w> ostream& operator<< (ostream& ost, fmt_setw<w> _) К>{ К> return ost << setw(w); К>}
что есть setw?
чуть не по теме:
если есть принятые стандарты сокращений, то я их еще не знаю (практики нет)...
только что не мог понять почему не собирается строка кода типа memcpy(a, b, c). просто привык к порядку (source, destination, length)!
К>template<char f> struct fmt_setfill {};
К>template<char f> ostream& operator<< (ostream& ost, fmt_setfill<f> _) К>{ К> return ost << setfill(f); К>}
мне нужно 2 параметра: &value, length
К>// связывание форматов К>// можно воспользоваться Loki::TypeList или boost::что-то-там-щас-не-помню
насчет связывания — я уже говорил: кодогенератор.... в начале написано почему...
всетаки это совсем не то что бы я хотел...
либо я паршиво описал что хочу (да я и сам вижу что паршиво ) либо вы не до конца вчитались...
но все равно спасибо за быстрый ответ. если есть еще какие идеи — всегда рад внимательно выслушать...
Здравствуйте, Oleg A. Bachin, Вы писали:
К>>Через поток — проще. Есть strstream, который выводит в строку. OAB>вероятно я не достаточно четко в конце описал почему через буффер удобнее (IMHO)... OAB>и сразу (забегая вперед)... под именнованным списком понималась именно структура! OAB>для чего? OAB>чтобы можно было сделать так:
OAB>class A
OAB>{
OAB> item_fmt<N> id(5);
OAB> item_fmt<C> first_name(50);
OAB>}
На С++ похоже. Но не С++.
<>
OAB>всетаки это совсем не то что бы я хотел... OAB>либо я паршиво описал что хочу (да я и сам вижу что паршиво ) либо вы не до конца вчитались...
Я попробую угадать, что тебе надо.
Итак, есть набор структур, для каждой из которых хочется построить вывод в строку (и ввод из строки). Т.е. это задача сериализации.
Причем выходная строка должна быть читаемой, поэтому и делаем всякие танцы с выравниванием.
Для каждого элемента структуры, если это примитивный тип, хочется правила вывода поместить прямо в объявление.
Примерно так:
Обобщенная задача решается на С++ довольно сложным путем.
Поэтому, если ты сможешь заузить и конкретизировать требования — это поможет продвинуться в решении задачи.
ЗЫ. Перед тем, как делать эскизы на С++ — попробуй выразить мысль на человеческом языке. И не старайся сразу углубляться в мелочи и детали. Devil in details, помнишь?
Вот! я так и знал! именно это я хотел услышать!
К>Я попробую угадать, что тебе надо.
ок...
К>Итак, есть набор структур, для каждой из которых хочется построить вывод в строку (и ввод из строки). Т.е. это задача сериализации. К>Причем выходная строка должна быть читаемой, поэтому и делаем всякие танцы с выравниванием.
точно!!! хотя и идея в другом — есть стандартизированный формат, придуман не мной. хочу сделать классы для удобных чтения/записи....
К>Для каждого элемента структуры, если это примитивный тип, хочется правила вывода поместить прямо в объявление. К>Примерно так: К>
здесь можно сузить...
т.е: есть порядка 15 типов... есть еще что-то типа перечисления, т.е.:
строка, которая может состоять только из '0', '1', '*', ' '
примерные типы я описывал. достаточно разобрать на строке — остальное я сам
К>А для всей структуры нужно что-то вида К>
STRINGIZE_MEMBERS(x,y,z);
угу... только хотелось бы как я писал выше... хотя возможно я опять мыслю не теми понятиями...
К>В общем, сделать метаданные своими руками.
да.
К>Обобщенная задача решается на С++ довольно сложным путем.
мы легких путей не ищем! особенно сейчас!
К>Поэтому, если ты сможешь заузить и конкретизировать требования — это поможет продвинуться в решении задачи.
пробуем так:
все что сказали выше, тип только строка с выравниванием влево (С)...
структура из двух элементов длинами 1 и 2...
вектор и итераторы — тоже домашнее задание.
К>ЗЫ. Перед тем, как делать эскизы на С++ — попробуй выразить мысль на человеческом языке. И не старайся сразу углубляться в мелочи и детали. Devil in details, помнишь?
в том то все и дело, что незнание мелочей мне сейчас мешает мыслить... я не могу представить как это вообще обычно делается (не то чтобы следать конкретную задачу).
Здравствуйте, Кодт, Вы писали:
К>Для каждого элемента структуры, если это примитивный тип, хочется правила вывода поместить прямо в объявление. К>Примерно так: К>
Ок. Что есть STRINGIZEABLE_MEMBER? Это macros или template?
Объясню почему мне это важно дальше...
К>А для всей структуры нужно что-то вида К>
STRINGIZE_MEMBERS(x,y,z);
К>В общем, сделать метаданные своими руками.
Ну в общем наверное больше да чем нет...
К>Обобщенная задача решается на С++ довольно сложным путем. К>Поэтому, если ты сможешь заузить и конкретизировать требования — это поможет продвинуться в решении задачи.
попробую конкретизировать:
у меня есть данные (входящие и исходящие). эти данные передаются в определенном формате.
в документации есть примерно следующее:
Типы данных:
"C" — строковый тип, выравнивание по левому краю, до длины добивается пробелами.
....
и т.д. все типы (как уже говорилось ~15 штук)
дальше
Структура файла 001:
Наименование какой-то фигни C[10]
Кол-во чего-то N[6]
.....
Таких структур порядка 50...
вот и хотелось бы иметь какое-то соответствие документация-код.
Все это собирается на лету. Я так понимаю, что Ваш пример подошел бы на тот случай, когда у меня уже есть какие-то бизнес объекты и мне захотелось из передать (сохранить состояние или что-то подобное).
1. почему хотелось бы иметь проверку формата до сериализации:
для проверки валидности данных. т.е. если у меня есть int, и ему при сериализации отведено 2 байта, то он не может быть больше 99. (ну и другие проверки нужны). в случае присвоения значения больше, я возбуждаю исключение. а дальше пусть внешний объект решает! строку может и обрежет, а может и нет... вобщем это уже бизнес-логика...
2. почему не хотелось бы иметь размерность, как параметр шаблона:
при варианте
template<int size, class format_style>
class item{}
item<1, C> i1;
item<2, C> i2;
item<3, C> i3;
item<4, C> i4;
компилятор создаст на 4 класса. (я ведь правильно понимаю?)
считаю это накладным...