Ассоциативный массив C++ с произвольными типами для значений

Qt5 должен поддерживаться. См. https://github.com/enthought/traitsui/blob/master/CHANGES.txt . Если у вас возникли проблемы с этим, пожалуйста, откройте вопрос о GH.


Обновление:

Попробуйте что-то вроде этого (частично, не проверено):

from traitsui.editors import ProgressEditor
(other imports etc)...

class ProgressDialog(HasTraits):
    progress = Int
    view = View(Item('progress', show_label=False,
                     editor=ProgressEditor(min=0, max=100)),
                title='Progress'
                )

8
задан gak 1 January 2009 в 10:35
поделиться

5 ответов

повышение:: вариант кажется точно, что Вы ищете.

14
ответ дан 5 December 2019 в 05:46
поделиться

Подкласс Value с IntValue, StringValue, и так далее.

2
ответ дан 5 December 2019 в 05:46
поделиться

Ваш подход был в основном в правильное направление. Необходимо будет знать тип, в который Вы помещаете. Можно использовать boost::any и Вы сможете поместить примерно что-либо в карту, пока Вы знаете то, во что Вы помещаете:

std::map<std::string, boost::any> table;
table["hello"] = 10;
std::cout << boost::any_cast<int>(table["hello"]); // outputs 10

Некоторые ответы рекомендовали использование boost::variant решить эту проблему. Но это не позволит Вам сохранить произвольные введенные значения в карте (как Вы требуемый). Необходимо знать набор возможных типов заранее. Учитывая, что, можно сделать вышеупомянутое более легко:

typedef boost::variant<int, std::string, void*> variant_type;
std::map<std::string, variant_type> table;
table["hello"] = 10;
// outputs 10. we don't have to know the type last assigned to the variant
// but the variant keeps track of it internally.
std::cout << table["hello"];

Это работает потому что boost::variant перегрузки operator<< с этой целью. Важно понять, что, если Вы хотите сохранить то, что в настоящее время содержится в варианте, все еще необходимо знать тип, как с в boost::any случай:

typedef boost::variant<int, std::string, void*> variant_type;
std::map<std::string, variant_type> table;
table["hello"] = "bar";
std::string value = boost::get<std::string>(table["hello"]);

Порядок присвоений на вариант является свойством времени выполнения потока управления Вашего кода, но тип, используемый любой переменной, определяется во время компиляции. Таким образом, если Вы хотите вытащить значение из варианта, необходимо знать его тип. Альтернатива должна использовать посещение, как обрисовано в общих чертах различной документацией. Это работает, потому что вариант хранит код, который говорит это, какой тип был в последний раз присвоен ему. На основе этого это решает во времени выполнения, какую перегрузку посетителя это использует. boost::variant является довольно большим и не абсолютно стандартный совместимый, в то время как boost::any стандартный совместимый, но использует динамическую память даже для маленьких типов (таким образом, это медленнее. вариант может использовать стек для маленьких типов). Таким образом, необходимо обменять то, что Вы используете.

Если Вы на самом деле хотите поместить объекты в него, которые отличаются только по способу, которым они делают что-то, полиморфизм является лучшим способом пойти. У Вас может быть базовый класс, из которого Вы происходите:

std::map< std::string, boost::shared_ptr<Base> > table;
table["hello"] = boost::shared_ptr<Base>(new Apple(...));
table["hello"]->print();

Который в основном потребовал бы этого расположения класса:

class Base {
public:
    virtual ~Base() { }
    // derived classes implement this:
    virtual void print() = 0;
};

class Apple : public Base {
public:
    virtual void print() {
        // print us out.
    }
};

boost::shared_ptr так называемый интеллектуальный указатель. Это удалит Ваши объекты автоматически, если Вы удалите их из своей карты, и ничто иное не ссылается на них их больше. В теории Вы, возможно, работали с простым указателем также, но использование интеллектуального указателя значительно увеличит безопасность. Прочитайте shared_ptr руководство, с которым я связался.

10
ответ дан 5 December 2019 в 05:46
поделиться

Можете Вы использовать объединение со станд.:: карта?

Повышение:: вариант обеспечивает переменные без типов.

Altrnatively Вы могли сделать все свои элементы данных Значения частными и обеспечить средства доступа, которые возвращают ошибку (или бросок), если это не установлено.

2
ответ дан 5 December 2019 в 05:46
поделиться

Простая оптимизация должна была бы использовать a union, так как у Вас всегда только будет одно из значений как ключ.

Больше полного решения инкапсулировало бы некоторую информацию о типе выполнения в интерфейс. Прежде всего, "Какой тип - это?" и, "Как я сравниваю значения для равенства?" Затем используйте реализации этого как ключ.

1
ответ дан 5 December 2019 в 05:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: