Гибридный (List + Dict) контейнер в C ++ 11

Можно ли обеспечить возможности std :: map и std :: vector в одном классе?

Если нет, что является препятствием?

Обратите внимание, что у меня нет опыта работы с stdlib, поэтому я заранее прошу прощения, если это глупая идея, которую стоит рассмотреть. Я хотел бы представить свой сценарий ниже, чтобы читатель мог понять, почему я рассматриваю эту альтернативу:


Я нахожусь на последних этапах переписывания оболочки C ++ для среды выполнения Python. Идея состоит в том, что мой проект C ++ способен выполнять скрипты Python.

В Python все PyObjectи у меня есть Object класс, упаковывающий PyObject* который может указывать на любой из дюжины встроенных типов Python (логическое значение, целое число, число с плавающей запятой, юникод, байты, множество, список, кортеж, словарь, вызываемый модуль).

Я хотел бы отразить типизацию хамелеона Python в C ++.

Так что если обернутым PyObject является {set, list, bytes, unicode, tuple}, то все это последовательности, поэтому я хотел бы иметь возможность делать такие вещи:

cout << my_seq[3]
my_seq[4] = foo
for( auto item : my_seq ) {...}

И если это словарь, я могу сделать:

my_dict["someKey"] = someValue;
for( auto kv_pair : my_seq ) {...}

и т.п.

Первоначальный проект имел класс SeqBase, который содержал необходимый контейнерный механизм stdlib для быстрого перечисления и т. Д. Begin, end, iterator, const_iterator и т. Д. И {set, list, bytes, unicode, tuple} был получен из этого. Код Вот.

Он также имел класс MapBase, который содержал различные начало, конец, итератор, const_iterator и т. Д. Код Вот.

Я хотел бы объединить эти два контейнера, чтобы все можно было обрабатывать из одного класса Object.

Но я совсем не уверен, возможно ли это.

Непосредственное препятствие, которое я вижу, это:

// SeqBase
typedef size_t size_type;
typedef seqref<T> reference;
typedef T const_reference;
typedef seqref<T> *pointer;
typedef int difference_type;
typedef T value_type; // TMM: 26Jun'01

// MapBase
typedef size_t size_type;
typedef Object key_type;
typedef mapref<T> data_type;
typedef std::pair< const T, T > value_type;
typedef std::pair< const T, mapref<T> > reference;
typedef const std::pair< const T, const T > const_reference;
typedef std::pair< const T, mapref<T> > pointer;

Похоже, эти typedefs должны существовать, чтобы алгоритмы stdlib обрабатывали объект. Но, похоже, мне нужно будет выбрать либо один набор, либо другой.
В четырех примерах указатель typedef отличается в обоих этих случаях.

Какие могут быть решения?

Возможно, я мог бы создать шаблон для Object и использовать метапрограммирование, чтобы разрешить Object и Object, возможно, использовать SFINAE для включения и выключения соответствующих итераторов.

Это выглядит, вероятно, хуже, чем подклассы, но я хотел бы видеть все варианты, которые у меня есть.

Я все еще задаюсь вопросом, есть ли какой-нибудь способ сделать это без необходимости уточнять заранее.

Я не беспокоюсь о создании кода, который может быть использован не по назначению, это обязанность потребителя не делать словарь в списке и т. Д.

(ПРИМЕЧАНИЕ: кроме того, я уже взломал проблему использования A["key"] = B[42] синтаксис типа для объектов типа последовательности и словарей. Единственная очевидная проблема, с которой я сталкиваюсь, это то, что я хотел бы включить быстрое перечисление: for(auto item:my_obj), но я еще не сфокусировался на конечном использовании, и я хотел бы упредить сценарии общего использования).

0

Решение

Если у меня нет чего-то важного, Boost.Container предоставляет flat_map которая в основном является картой, построенной поверх вектора.

Если вы не определили карту нормалей (unordered_) в качестве медленной точки в вашей программе, я бы не решился отойти от нее, хотя …

1

Другие решения