Отображение векторов произвольного типа
Мне нужно хранить список векторов разных типов, на каждый из которых будет ссылаться идентификатор строки. Сейчас я использую std::map
с std::string
в качестве ключа и boost::any
как это значение (пример реализации размещен здесь).
Я отклеился при попытке запустить метод для всех сохраненных векторов, например:
std::map<std::string, boost::any>::iterator it;
for (it = map_.begin(); it != map_.end(); ++it) {
it->second.reserve(100); // FAIL: refers to boost::any not std::vector
}
Мои вопросы:
- Можно ли разыграть
boost::any
к произвольному векторному типу, чтобы я мог выполнять его методы? - Есть ли лучший способ отобразить векторы произвольных типов и затем извлечь их с правильным типом?
В настоящее время я играю с альтернативной реализацией, которая заменяет boost::any
с указателем на базовый контейнерный класс, как предлагается в этом ответе. Это открывает новую банку червей с другими проблемами, которые мне нужно решить. Я рад пойти по этому пути в случае необходимости, но мне все еще интересно знать, смогу ли я заставить его работать с boost::any
, если есть другие лучшие решения.
PS Я новичок в C++ n00b (и глупо избалован динамической типизацией Python слишком долго), так что я вполне могу поступить неправильно. Жесткая критика (в идеале сопровождаемая предложениями) очень приветствуется.
Большая картина:
Как отмечено в комментариях, это может быть проблемой XY, так что вот краткий обзор того, чего я пытаюсь достичь.
Я пишу планировщик задач для среды моделирования, которая управляет выполнением задач; каждая задача является элементарной операцией над набором векторов данных. Например, если task_A
определяется в модели как операция на "x"(double), "y"(double), "scale"(int)
то, что мы фактически пытаемся подражать, это исполнение task_A(double x[i], double y[i], int scale[i])
для всех значений i
,
Каждая задача (функция) работает с различными подмножествами данных, поэтому эти функции имеют общую сигнатуру функции и имеют доступ к данным только через определенные API, например get_int("scale")
а также set_double("x", 0.2)
,
В предыдущем воплощении фреймворка (написанном на C) задачи планировались статически, и фреймворк генерировал код на основе заданной модели для запуска симуляции. Порядок задач основан на графике зависимостей, извлеченном из определения модели.
Сейчас мы пытаемся создать общую среду выполнения для всех моделей с помощью планировщика времени выполнения, который выполняет задачи по мере удовлетворения их зависимостей. Переход от генерации специфичного для модели кода к универсальному вызвал все виды боли. По сути, мне нужно иметь возможность обрабатывать гетерогенные векторы и обращаться к ним по "имени" (и, возможно, type_info
), отсюда и вышеупомянутый вопрос.
Я открыт для предложений. Любое предложение.
1 ответ
Просматривая добавленные детали, я немедленно решил разделить данные на несколько отдельных карт с типом в качестве параметра шаблона. Например, вы бы заменить get_int("scale")
с get<int>("scale")
а также set_double("x", 0.2)
с set<double>("x", 0.2);
В качестве альтернативы, используя std::map
Вы могли бы довольно легко изменить это (для одного примера) на что-то вроде doubles["x"] = 0.2;
или же int scale_factor = ints["scale"];
(хотя вам может потребоваться немного остерегаться последнего - если вы попытаетесь получить несуществующее значение, оно будет создано с инициализацией по умолчанию, а не с сообщением об ошибке).
В любом случае, вы получаете множество отдельных коллекций, каждая из которых является однородной, вместо того, чтобы пытаться собрать несколько коллекций разных типов в одну большую коллекцию.
Если вам действительно нужно собрать их в одну общую коллекцию, я бы подумал об использовании структуры, чтобы она стала чем-то вроде vals.doubles["x"] = 0.2;
или же int scale_factor = vals.ints["scale"];
По крайней мере, не случайно, я не вижу, чтобы это что-то теряло, и, сохраняя статическую типизацию во всем, это, безусловно, лучше соответствует тому, как C++ предназначен для работы.