2015-06-05 2 views
2

мне нужен std::map контейнера есть что-то вроде:Есть ли способ иметь зЬй :: карты без объявить тип значения

[ "a" => [ "a1" => [ "a11" => 1, "a12" => 0 ], "a2" => 1 ] ]

  1. Ключа "a1" имеет значение другого std::map, но ключ "a2" имеет значение integer. В этой ситуации, как я могу объявить карту?

  2. Есть ли способ изменить значение на другой тип? Например, если я хочу изменить значение "a12" на std::vector?

Спасибо.

+1

Некоторые простые советы, это гораздо проще сделать с динамическими языками, такими как python и ruby. Статическая типизация не поддается этой проблеме. Существует много возможных решений, но все они связаны с типами внедрения в код приложения, вероятно, непригодными. – ceorron

+0

@ceorron Спасибо, да, это намного проще сделать в python и ruby. На самом деле, у меня возникла эта проблема, когда я пытался перевести код python в C++. –

ответ

4

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

+0

Спасибо, 'boost :: any' работает для меня. –

0

Я не мог полностью понять ваш вопрос. Что я получил, так это то, что вы хотите вставлять разные типы значений. Первый ключ будет содержать «int Value» другой карты, на которую указывает другой ключ этой карты. второй ключ будет содержать одно целое число. Если это так, то почему бы не использовать вектор внутри карты.

std::map<int, std::vector<int>> mymap; 
std::vector <int> vec; 
vec.push_back(5); 
mymap.insert(make_pair(1, vec)); 

В дополнение к этому, если вы не уверены в типе данных. вы также можете использовать вложенные карты. для второго элемента просто введите фиктивный ключ.

std::map<int, std::map<int,int>> mymap; 
std::map <int, int> mappy; 
mappy.insert(make_pair(0,5)); 
mymap.insert(make_pair(1, mappy)); 

Это решение проблемы?

0

Ключ «a1» имеет значение другой std :: map, но ключ «a2» имеет значение integer. В этой ситуации, как я могу объявить карту?

Вы не можете декларировать такую ​​карту. Все значения карты имеют один и тот же тип.

Есть ли способ изменить значение на другой тип? Например, если я хочу изменить значение «a12» на std :: vector?

Вы, наверное, имели в виду, «Есть ли способ Ставить на тип переменной в другую». Ответ - нет.

Однако можно определить тип, который может вставлять данные любого типа внутри. Это не совсем просто реализовать, но вам повезло, Boost внедрил такой тип: boost::any. Затем карта с таким типом значений может содержать значение любого типа, заключенного в объект any. Я бы рекомендовал пересмотреть ваш дизайн, чтобы вам не нужно было иметь объекты любого типа.

0

Нет, каждый тип контейнера STL нуждается в точном ОДНОМ типе. Для вашей идеи вам нужен тип контейнера, который может содержать несколько типов. Для этого вы можете использовать http://www.boost.org/doc/libs/1_58_0/doc/html/variant.html

1

при использовании std :: map вам нужно указать тип значения.Если вы хотите отобразить на объекты разных типов, я думаю, у вас есть две возможности:

Определить базовый класс для значения и объявить карту

std::map<int, base_class_t *> 

или, Чем лучше

std::map<int, shared_ptr<base_class_t>> 

Затем вы можете вставлять разные объекты, все полученные из base_class_t.

Варианты outher - это карта для объединения. Но я бы этого не делал ;-)

0

Я думаю, вероятно, что частичный шаблонный шаблон с одним параметром может быть ответом на вашу проблему, что-то вроде этого;

template <typename T> 
class partialMap : public std::map<int,T> 
{ 
}; 

int main() 
{ 
    //vector example 
    std::vector <int> vec; 
    partialMap<std::vector<int>> _vecMap; 
    vec.push_back(5); 
    _vecMap.insert(make_pair(1, vec)); 
    //map example 
    std::map<int,int> map; 
    partialMap<std::map<int,int>> _mapMap; 
    vec.push_back(5); 
    _mapMap.insert(make_pair(1, map)); 
} 

Таким образом, вы можете использовать нечетко тот же класс с первым параметром, предопределенного и второй, определенной в функции, что вам нужно.

Смежные вопросы