Если вам не нужен полный урок, вам следует ознакомиться с шаблоном FlyWeight .Он предназначен для экономии памяти.
РЕДАКТИРОВАТЬ: извините, пауза во время обеда;)
Типичный подход FlyWeight заключается в разделении свойств, которые являются общими для большого числаобъектов из свойств, которые типичны для данного экземпляра.
Как правило, это означает:
struct Light
{
kind_type mKind;
specific1 m1;
specific2 m2;
};
kind_type
часто является указателем, однако в этом нет необходимости.В вашем случае это будет реальная трата, потому что сам указатель будет в 4 раза больше «полезной» информации.
Здесь я думаю, что мы могли бы использовать заполнение для хранения идентификатора.В конце концов, как вы сказали, он будет расширен до 16 бит, хотя мы используем только 9 из них, поэтому давайте не будем тратить остальные 7!
struct Object
{
double quantity;
bool flag;
unsigned char const id;
};
Обратите внимание, что порядок элементов важен:
0x00 0x01 0x02 0x03
[ ][ ][ ][ ]
quantity flag id
0x00 0x01 0x02 0x03
[ ][ ][ ][ ]
id flag quantity
0x00 0x02 0x04
[ ][ ][ ][ ][ ][ ]
id -- quantity flag --
Я не понимаю бит "расширенный во время выполнения".Кажется страшнымЭто какой-то самоизменяющийся код?
Шаблон позволяет создать очень интересную форму FlyWeight: Boost.Variant .
typedef boost::variant<Car,Dog,Cycle, ...> types_t;
Вариант может содержатьлюбой из перечисленных здесь типов.Он может управляться «обычными» функциями:
void doSomething(types_t const& t);
Может храниться в контейнерах:
typedef std::vector<types_t> vector_t;
И, наконец, способ работы с ним:
struct DoSomething: boost::static_visitor<>
{
void operator()(Dog const& dog) const;
void operator()(Car const& car) const;
void operator()(Cycle const& cycle) const;
void operator()(GenericVehicle const& vehicle) const;
template <class T>
void operator()(T const&) {}
};
Очень интересно отметить поведение здесь.Нормальное разрешение перегрузки функции происходит, поэтому:
- Если у вас есть
Car
или Cycle
, вы будете использовать их, каждый второй потомок GenericVehicle
будет использовать 4-ую версию - Можно указать версию шаблона в качестве перехвата всех и указать ее соответствующим образом.
Замечу, что не шаблонные методы могут быть совершенно определены в файле .cpp.
Чтобы применить этого посетителя, вы используете метод boost::apply_visitor
:
types_t t;
boost::apply_visitor(DoSomething(), t);
// or
boost::apply_visitor(DoSomething())(t);
Второй способ кажется странным, но это означает, что вы можете использовать его наиболее интересным способом, как предикат:
vector_t vec = /**/;
std::foreach(vec.begin(), vec.end(), boost::apply_visitor(DoSomething()));
Читайте по варианту, это наиболее интересно.
- Проверка времени компиляции: вы пропустили один
operator()
?компилятор выдает - Нет необходимости в RTTI: нет виртуального указателя, нет динамического типа -> так же быстро, как при использовании объединения, но с повышенной безопасностью
Конечно, вы можете сегментироватьваш код, определив несколько вариантов.Если некоторые разделы кода имеют дело только с 4/5 типами, используйте для этого определенный вариант:)