Я собираюсь предвосхитить это, сказав, что, возможно, C ++ не является подходящим языком для всего, что вы пытаетесь достичь. Чем больше вы пытаетесь контролировать свою программу с помощью внешних данных, тем ближе вы подходите к сценариям. И есть много более мощных вариантов, когда это ваша цель.
При этом, конечно, это возможно, хотя и не так легко. Два способа сразу приходят на ум. Первый - требовать, чтобы все применимые типы имели конструктор, который принимает std::string
. Этот конструктор будет отвечать за собственный синтаксический анализ.
template<typename T> Base * createInstance(const std::string& s) { return new T(s); }
typedef std::map<std::string, Base*(*)(const std::string&)> map_type;
//...and similar changes as needed
Если вы не хотите изменять определения типов или это неприемлемо в противном случае [возможно, у ваших типов уже есть такой конструктор?], Избавьтесь от шаблона createInstance
и предоставьте индивидуальные версии для каждого типа, который вы используете. интересует. Эта функция выполняет разбор и вызывает соответствующий конструктор.
map["derivedA"] = createDerivedA;
map["derivedB"] = createDerivedB;
Третий вариант может быть возможен при использовании вариадических шаблонов [или вариабельных шаблонов в стиле boost-esque], которые вернут вас к первоначальной простоте.
template<typename T, typename... Args>
Base* create(std::string) {
//somehow pass the string to a generic function that packs the arguments into a tuple
//then somehow unpack that tuple and pass the bits to the constructor
}
map["derivedA"] = create<derivedA, int, double, std::string>;
Однако я понятия не имею, как это осуществить, и даже если это возможно.