среда, 5 апреля 2017 г.

Фокусы с 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, конвертируя в нужный тип. Без дополнительных проверок это небезопасно, но если вы знаете, что делаете - очень полезно.

Комментариев нет:

Отправить комментарий