| Comments: |
зачем юзать any, если у тебя ограниченный список типов? используй boost.variant. он требует динамического выделения памяти и очень легко стримится.
он требует динамического выделения памяти Имелось в виду, «не требует»?
зачем юзать any, если у тебя ограниченный список типов? Список ограниченный, но большой, порядка 10. Типы оперделяются на этапе выполнения (считываются из файла). Типы всякие, например, boost::rational<N, D>.
используй boost.variant. Тут есть несколько соображений.
* Boost.Variant я когда-то разбирал, когда ещё маленький был :) Как его толково использовать я тогда, чесгря, ниасилил. Надо заново свежим взглядом глянуть. Помню, static_visitor ещё нормально пошёл, а вот на recursive_wrapper мозг уже пообещал взорваться.
* «Шаблонность» и «стековость», быть может, способны уменьшить время работы программы. Но наверняка в разы увеличат время её написания (об этом чуть позднее). Да и компиляция, уверен, станет длиться нехилое время.
* Я так понимаю, что можно решить, будто я характерный C++-извращенец, но это не так :) Если извраты не сильно далеко заходят, я этому только рад (хе-хе, шутка), но начиная с некоторого момента это начинает напрягать.
Тут есть ещё такая аналогия: Boost.Regexp и Boost.Xpressive. Первое — обычная библиотека regexp'ов, она примерно так же выглядела бы на любом языке. Второе — сугубо плюсовое достижение. Там всё statically checked и compile time. Короче, DSEL (domain-specific embedded langauage, afair) на базе ужасного синтаксиса C++. И от него реально тошнит. Похожая штука и с Boost.Spirit. Короче, невзлюбил я с первого взгляда Variant, Xpressive и Spirit. Впрочем, оставляю за собой право передумать :)
* Помню, у вас, геймдевщиков, как-то холивар состоялся (на dtf, емнип). На тему «саттеры, мэйерсы, александреску и студенты любители c++-дрочерства умных книжек». А теперь представь, выдаю я на работе нагора исходник, а там сплошь boost::make_recursive_variant_over и boost::apply_visitor. Нафиг моим коллегам такие расклады — с утра в понедельник увидеть это? :)
Ну, в общем, Boost.Variant я подробнее посмотрю. Но Boost.Any намного проще, это немаловажно.
А у вас в конторе приветствуется Boost.Variant?
Аналогия с Boost.Regexp и Boost.Xpressive немного не верна. Кстати икспрессив может и рантайм рекэкспы обрабатывать.
Между boost.variant и boost.any есть принципиальная разница. Вариант это такой высокоуровневый юнион. Значение переменной хранится прямо в нём. А boost.any - это что-то типа pImpl. any требует динамического выделения памяти для хранения значения переменной.
Any более гибок, так как может хранить в себе любое значение. А Variant более дешёв. Как в создании\копировании, так и в кастах. Касты там осуществлются по средством визитора, который по сути является оператором switch и от этого он очень быстрый.
в Any же каст требует сравнения typeid, а это значит сравнение строк, операция не из дешёвых. Ну и копирование требует выделения памяти. Что тоже не очень приятно и ведёт к фрагментации оперативной памяти, особенно на маленьких типах, типа int, double, string и т.д.
Короче, резюме такое. На выбор либо быстрый и дешёвый compile-time контейнер. Либо медленный и дорогой run-time контейнер. Иногда нужно первое, а иногда второе.
в Any же каст требует сравнения typeid, а это значит сравнение строк, операция не из дешёвых. Оператор typeid возвращает ссылку на type_info. Как для него реализован оператор operator ==() зависит от реализации. Но почему ты решил, что он сравнивает строки? 0_о
нормальное введение. на медиазоне приницпиально не пишем? =)
Ок, напишу как-нибудь и на Медиазоне ;)
*Тут выпендрёжа ради переменная объявляется а заголовке условного оператора (как в for'е), и видна только в скоупе if'а. В реальном коде такое встречается редко*
Причём тут выпендрёж? Это очень полезная и нужная конструкция. И должна использоваться в реальном коде везде где используется динамик_каст по указателю(или аналогичный каст типа any_cast).
Ну и на счёт базового класса. По-моему, использование boost.any в качестве базового класса идиологически ничем не отличается от использования void*. В функции void ButtonOnClick(boost::any sender, EventArgs args) в sender, как и в случае с void*, может лежать абсолютно что угодно. Интерфейса полезного boost.any не выставляет. Так что ничего полезного этот тип не даёт.
Куда полезнее будет обработчик с такой сигнатурой: void ButtonOnClick(gui::Control& sender, EventArgs args).
Это очень полезная и нужная конструкция. Я согласен. И сожалею, что в исходниках моих коллег встречается редко. Вот и напомнил, что так тоже можно (нужно). Эта конструкция полезна ещё и из общих соображений локальности имён.
Куда полезнее будет обработчик с такой сигнатурой: void ButtonOnClick(gui::Control& sender, EventArgs args).
Тут я согласен :-` неудачный пример. Возможно, логичнее было бы boost::any взять вместо EventArgs, в качестве корня иерархии, где базовый класс пуст (так как не содержит общих для всех функций элементов). У меня такое было как-то: была простая фабрика, там регистрировались функции-creator'ы. Вот аргументы, требующиеся для создания объектов, были разные, там Boost.Any был вполне уместен. Как альернатива пустому базовому классу BaseCreationArgs.
По-моему, использование boost.any в качестве базового класса идиологически ничем не отличается от использования void*. В функции void ButtonOnClick(boost::any sender, EventArgs args) в sender, как и в случае с void*, может лежать абсолютно что угодно. Интерфейса полезного boost.any не выставляет.
0_o Если за void* будет лежать что-то левое, то проверить корректность даун_каста нельзя будет, так ведь? В предложенном же варианте any_cast вернёт NULL или исключение, если в аргументе что-то левое.
>// Жаль, что в C# нельзя сделать что-нибудь вроде >// namespace swf = System.Windows.Forms;
Вобщем-то можно... using swf = System.Windows.Forms;
От холера, а мужики-то не знают! Книшку, что ли, по C# почитать...
From: (Anonymous) 2007-12-29 12:05 am (UTC)
тип потока и невставляемые объекты | (Link)
|
Привет!
1) А нельзя ли как-нибудь сделать так, чтобы можно было Utils::Any вставлять в любой поток basic_ostream<?> (например, std::wostream)?
2) Не такой уж Utils::Any, т.к. он не работает с типами, для которых не определён оператор вставки в поток. Не могу найти откуда взялся is_default_streamable, по-этому приведу его код:
// (C) Copyright David Abrahams 2004. // (C) Copyright Jonathan Turkanis 2004. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.
#ifndef BOOST_IOSTREAMS_DEFAULT_INSERTABLE_HPP_INCLUDED #define BOOST_IOSTREAMS_DEFAULT_INSERTABLE_HPP_INCLUDED
#include <iosfwd> #include <boost/type_traits/remove_cv.hpp> #include <boost/type_traits/add_reference.hpp> #include <boost/mpl/bool.hpp> #include <boost/detail/workaround.hpp>
namespace boost { namespace io {
// This namespace ensures that ADL doesn't mess things up. namespace default_insertable_ {
// a type returned from operator++ when no increment is found in the // type's own namespace struct tag { }; // any soaks up implicit conversions and makes the following // operator<< less-preferred than any other such operator that // might be found via ADL. struct any { template <class T> any(T const&); };
// This is a last-resort operator<< for when none other is found template<typename Ch, typename Tr> tag operator<<(std::basic_ostream<Ch, Tr>&, const any&);
// two check overloads help us identify which operator<< was picked char (& check(tag) )[2]; template<typename Ch, typename Tr> char check(std::basic_ostream<Ch, Tr>&); template<typename T, typename Ch, typename Tr> struct impl { static typename add_reference< typename remove_cv<T>::type >::type t; static std::basic_ostream<Ch, Tr>& out;
BOOST_STATIC_CONSTANT( bool, value = sizeof(default_insertable_::check(out << t)) == 1 ); };
} // End namespace default_insertable_.
template< class T, typename Ch = char, typename Tr = std::char_traits<Ch> > struct is_default_insertable : mpl::bool_< ::boost::io::default_insertable_::impl<T, Ch, Tr>::value > { };
} } // End namespace boost::io.
#endif // BOOST_IOSTREAMS_DEFAULT_INSERTABLE_HPP_INCLUDED
Спасибо за статью.
-MyXa-
![[User Picture]](http://l-userpic.livejournal.com/43376717/9763421) | From: bik_top 2007-12-29 02:07 pm (UTC)
Re: тип потока и невставляемые объекты | (Link)
|
Видимо, с этим кодом я уже в новом году разбираться буду, т. к. прям щаз собираюсь сваливать в горы :) | |