Отображение векторов произвольного типа

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

Другие вопросы по тегам