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

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

P.S. Я новичок в 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), отсюда и вопрос выше.

Я открыт для предложений. Любое предложение.


person Shawn Chin    schedule 03.05.2012    source источник
comment
Мне это кажется классическим случаем проблемы XY. То, что вы пытаетесь сделать, просто очень плохо подходит для C++. Вероятно, вам нужно немного отступить и рассказать нам, чего вы на самом деле пытаетесь достичь. Однако прямо сейчас кажется (по крайней мере мне), что вы пишете не на C++; вы пишете Python с синтаксисом C++.   -  person Jerry Coffin    schedule 03.05.2012
comment
Я бы согласился. Вы, конечно, не можете делать то, что хотите, с boost::any без множества неприятных прыжков через обручи, чтобы точно отслеживать, какой тип вектора хранится в каждом слоте, так что пришло время сделать шаг назад и снова взглянуть на всю проблему, потому что скорее всего, вы используете неправильный тип данных. На самом деле это обычно происходит всякий раз, когда any начинает казаться возможным. Он имеет свое место, но оно не большое.   -  person Matthew Walton    schedule 03.05.2012
comment
@JerryCoffin Я тоже согласен. Конечно, кажется, что я иду против сути языка с камнями преткновения на каждом шагу. Я посмотрю, что я могу сделать, чтобы описать общую картину — я опасаюсь превращать это в вопрос это моя проблема, придумать решение для меня, который вполне может оказаться слишком сложным и, вероятно, неправильным. -topic для переполнения стека.   -  person Shawn Chin    schedule 03.05.2012
comment
@JerryCoffin Я добавил некоторый обзор того, что я пытаюсь сделать. Надеюсь, поможет. (p.s. Я скоро отключусь, но рассмотрю все отзывы, как только смогу)   -  person Shawn Chin    schedule 03.05.2012
comment
Похоже, вам не нужно хранить все векторы на одной карте. Почему бы не иметь по одной карте для каждого типа?   -  person n. 1.8e9-where's-my-share m.    schedule 03.05.2012
comment
@н.м. К сожалению, список типов заранее не известен и не ограничивается примитивными типами. Я думал о карте карт, но это очень быстро стало очень запутанным.   -  person Shawn Chin    schedule 04.05.2012
comment
@matthew Я согласен с вашими чувствами, и мне было неудобно полагаться на boost::any, отсюда и крик о помощи, которым является этот вопрос.   -  person Shawn Chin    schedule 04.05.2012
comment
«список типов заранее неизвестен» — список типов всегда известен заранее. Любая программа может работать только с фиксированным набором типов. Вы не можете создавать новые типы во время выполнения. Если типы неизвестны фреймворку, они известны пользователю фреймворка. В последнем случае позвольте пользователю указать вашей структуре, какие типы использовать.   -  person n. 1.8e9-where's-my-share m.    schedule 04.05.2012
comment
@н.м. Справедливо. Я перефразирую это - мне нужно обрабатывать произвольные числа разных типов, поэтому явное создание одной карты для каждого типа может быть не вариантом. Платформа предоставит пользователям подпрограммы для регистрации их типов и имен векторов, использующих этот тип.   -  person Shawn Chin    schedule 04.05.2012
comment
Чтобы использовать N типов, вам нужно O(N) строк кода только для объявления C API. Вы должны явно создать что-то для каждого типа. Если вы делаете то, что предлагает Джерри Коффин, вам не нужно явно создавать карты. Вам все равно придется явно создавать C API, независимо от того, какое решение C++ вы используете.   -  person n. 1.8e9-where's-my-share m.    schedule 04.05.2012
comment
Согласованный. У нас есть то преимущество, что каждая модель, управляемая C, проходит фазу синтаксического анализа до того, как функции будут скомпилированы, поэтому именно здесь мы генерируем C API для конкретной модели. Планировщик, который запускает функции, не имеет такой роскоши.   -  person Shawn Chin    schedule 04.05.2012


Ответы (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++.

person Jerry Coffin    schedule 03.05.2012
comment
Я, вероятно, должен был добавить, что 1) API-интерфейсы доступа должны быть доступны для функций C также по устаревшим причинам, следовательно, избегая параметров шаблона, и 2) типы не ограничены примитивами и могут быть определяемыми пользователем типами данных, поэтому я Мне все еще нужно управлять моей коллекцией карт, если я буду поддерживать их однородность. В любом случае, я обдумаю ваши предложения и решу их, когда вернусь к своему рабочему столу утром. Большое спасибо за ваш вклад. - person Shawn Chin; 04.05.2012