Массив шаблонных экземпляров классов - PullRequest
2 голосов
/ 22 мая 2019

Я пишу парсер аргументов командной строки для приложения. Они могут быть трех типов: логические, строковые или числовые. Данный аргумент будет ожидать данного типа, поэтому здесь нет догадок.

Я решил представить аргумент в виде класса с именем Arg. Один и тот же переключатель может появляться несколько раз, поэтому я хочу отслеживать идентичность, отсюда и класс.

Дело в том, что, хотя в игре несколько типов, обработка всегда более или менее одинакова. Чтобы избежать написания кода, я подумал, что могу создать шаблон класса Arg, по сути, так:

class Arg(T)
{
    public:
        T value;

        this(T defaultValue)
        {
            value=defaultValue;
        }
}

Моя проблема в том, что в идеале я бы просто складывал их в динамический массив, но сначала мне нужно было бы узнать их тип: я не могу точно объявить массив как Arg!whatever[] myArray.

Я, очевидно, могу использовать базовый тип, что-то вроде Object[] array. Дело в том, что мне нужно будет привести каждый элемент массива перед его использованием. Я мог бы написать вспомогательную функцию для этого, но это вряд ли кажется идиоматическим. Я бы, однако, держал все связанные с типом боли в одной функции. (это то, что я бы сделал без внешнего совета)

Полагаю, я мог бы также поддерживать отдельные массивы. Но это не слишком удобно: мне нужно подумать о различных числовых типах, и если бы я добавил новые типы аргументов, мне пришлось бы добавить новые массивы.

Я также пытался использовать std.variant, но не нашел их слишком удобными для моих целей. Возможно, я использовал их неправильно, но я обнаружил, что мне приходится писать точно такие же функции с несколькими сигнатурами в форме:

Algebraic!(string, bool, int) value;        

this(string defaultValue) { this.value=defaultValue; }
this(  bool defaultValue) { this.value=defaultValue; }
this(   int defaultValue) { this.value=defaultValue; }

Что вряд ли похоже на умную работу.

Как правильно поступить?

Спасибо за помощь!

1 Ответ

2 голосов
/ 23 мая 2019

Что именно не так с использованием std.variant? Вместо того, чтобы записывать все эти различные перегрузки, вы можете просто использовать шаблонные функции:

class Arg
{
    private Algebraic!(string, bool, int) value;

    this(T)(T defaultValue) if (is(T : string) || is(T : bool) || is(T : int))
    {
        this.value = defaultValue;
    }
}
...