Фокусы с Compound
Недавно столкнулся с интересной задачей: описанием класса, который инкапсулирует неизвестный заранее набор объектов. Типы этих объектов задаются через variadic template – то есть, шаблон с переменным количеством параметров. Статические массивы для этой задачи, ясное дело, не годятся, но тут идеально подошел Compound из dlib.core.compound. Это своеобразный “гибрид” кортежа и структуры – составной тип данных, который можно создавать в шаблонах. Ему можно передавать кортеж параметров variadic-шаблона, и это позволяет проделывать замечательные вещи.
class Collection(C...)
{
protected Compound!C _components;
this(C comps)
{
_components = comps;
}
}
auto inc = new Collection!(int, char, bool)(10, 'a', false);
Проблема с обычными кортежами (Tuple) в том, что их нельзя возвращать из функции. Но Compound – можно. Таким образом, для ридонли-доступа к _components мы можем объявить следующий метод:
auto components() @property
{
return _components;
}
А еще мы можем заполнять Compound в цикле, читая значения, например, из массива:
this(int[] arr)
{
foreach(i, T; C)
{
_components[i] = cast(T)arr[i];
}
}
auto inc = new Collection!(int, char, bool)([5, 40, 0]);
Пример бессмысленный, но наглядный – мы проходим по всем типам кортежа C и записываем входное значение в наш Compound, конвертируя в нужный тип. Без дополнительных проверок это небезопасно, но если вы знаете, что делаете – очень полезно.