Фабричный шаблон C ++ с ограничением гетерогенного конструктора - PullRequest
6 голосов
/ 19 декабря 2011

Я реализую программу на C ++, которая может программно создавать экземпляры объектов, используя входной файл, который предоставляет имена классов и аргументы для передачи конструкторам.

Классы являются производными от общего базового класса, но их конструкторсигнатура может быть разной.

Они объявлены следующим образом:

class Base { ... }
class Class1 : Base { Class1(int a1, int a2); }
class Class2 : Base { Class2(int a1, int a2, int a3); }
... and so on...

Типы аргументов не обязательно должны быть целыми числами, фактически они могут быть любым встроенным типом или сложным, настраиваемым типом.

Ввод программы может выглядеть следующим образом в форме JSON:

[
  { "Class1": ["arg11", "arg12"] },
  { "Class2": ["arg21", "arg22", "arg23"] },
  ...and so on...
]

Считывание документов для Boost.Functional / Factory похоже, что это может решить мою проблемуесли бы не тот факт, что в моем приложении сигнатура конструктора меняется (ограничение гетерогенности).Подход Boost.Function / Factory заключается в нормализации сигнатур конструктора, однако это невозможно в моем приложении.

В динамическом языке, таком как Python, это было бы довольно тривиально: obj = klass(*args), где klass = Class1 и args = ["arg11, "arg12"].

Так, как можно было бы реализовать шаблон фабрики с гетерогенным ограничением в C ++?

Существуют ли другие библиотеки, кроме Boost, которые я пропустил, которые могут помочь?

Можно ли реализовать это так, чтобы единственной зависимостью была стандартная библиотека (т.е. без Boost)?

Кроме того, в случае, когда аргумент конструктора имеет сложный тип, так что он должен быть специальноКак это влияет на сложность проблемы, построенную по JSON-представлению?

Ответы [ 2 ]

5 голосов
/ 20 декабря 2011

Рассматривали ли вы наличие фабричного метода для каждого класса, который знает, как создать объект из "массива" параметров, считанных из файла.

То есть:

// declared "static" in header file
Class1* Class1::FactoryCreate(int argc, const char** argv)
{
    if (argc != 2)
        return NULL; // error

    int a1 = atoi(argv[0]);
    int a2 = atoi(argv[1]);
    return new Class1(a1, a2, a3);
}

// declared "static" in header file
Class2* Class2::FactoryCreate(int argc, const char** argv)
{
    if (argc != 3)
        return NULL; // error
    int a1 = atoi(argv[0]);
    int a2 = atoi(argv[1]);
    int a3 = atoi(argv[2]);
    return new Class2(a1, a2, a3);
}
1 голос
/ 20 декабря 2011

Чтобы достичь того, чего вы хотите, вам понадобится, в какой-то момент в вашем коде, гигантское switch заявление, чтобы решить, какой класс создать на основе имени (на самом деле switch не будет работать, потому что выне может включать строки - больше похоже на очень длинный if - else if).

Кроме того, кажется, что отображаемое вами представление не содержит никакой информации о типе аргументов конструктора.Это может быть проблемой, если у вас есть класс, который может вызывать несколько конструкторов с одинаковым количеством аргументов.

В конце я думаю, что лучше всего, если вы пойдете с чем-то вроде @ selbies answer , но используйте генерацию кода, чтобы сгенерировать код конструкции для вас.

...