-
Автор темы
- #1
Из описания понятно, что это контейнер хранения данных и применение его иногда здорово упрощает тривиальные задачи и дает несравненный плюс как в "реализации кода по скиллу", так и в упрощении и сокращении кода.std::map — отсортированный ассоциативный контейнер, который содержит пары ключ-значение с неповторяющимися ключами
При написании проекта резко встала необходимость как-то упростить себе работу с std::map и сократить и так огромный код.
Что и как работает в подробностях объяснять не буду, а просто прокомментирую код доступным языком:
Код:
#pragma once
#include <map>
#include <memory>
class MapList
{
protected:
/*структура для типов переменных*/
struct cType
{
cType(const type_info* t) : m_type(t) {};
const type_info* m_type;
};
/*структура хранения объекта значения*/
template< typename T>
struct cObject :
public cType
{
cObject(const T& d) : cType(&typeid(T)), m_Objectdata(d) {};
T m_Objectdata;
};
private:
/*рабочий контейнер std::map*/
std::map<std::size_t, std::shared_ptr<cType>> m_pList;
public:
/*записываем значение*/
template<typename T>
T* set(const std::string& key, const T& data)
{
std::size_t szKey = std::hash<std::string>()(key);
m_pList[szKey] = std::shared_ptr<cType>(new cObject<T>(data));
return &static_cast<cObject<T>*>(m_pList[szKey].get())->m_Objectdata;
};
/*получаем ссылку на объект по ключу*/
template <typename T>
T* get(const std::string& key)
{
auto find = m_pList.find(std::hash<std::string>()(key));
if (&typeid(T) == find->second.get()->m_type)
{
if (find != m_pList.end())
return &static_cast<cObject<T>*>(find->second.get())->m_Objectdata;
}
return nullptr;
}
};
Теперь поговорим о практическом применении:
для начала простой пример использования. Заполняем данные:
Код:
MapList mymap;
mymap.set<int>("Key1", 12345);
mymap.set<float>("Key2", 0.73f);
mymap.set<std::string>("Key3", "mystring");
теперь попробуем получить данные:
- Вариант 1(указатель).: так как функция get возвращает нам ссылку на объект, то мы можем контролировать полученные данные и написать так:
Код:
int *Key1 = mymap.get<int>("Key1");
if (Key1)
std::cout << *Key1 << std::endl;
Вариант 2(данные). если на 100% уверены в существовании данных по указанному ключу, то мы с легкостью можем получать сразу значение переменной:
Код:
float Key2 = *(float*)mymap.get<float>("Key2");
std::cout << "Key2 = " << Key2 << std::endl;
Код:
MapList mymap;
mymap.set<int>("Key1", 12345);
mymap.set<float>("Key2", 0.73f);
mymap.set<std::string>("Key3", "mystring");
auto Key1 = mymap.get<int>("Key1");
if (Key1)
std::cout << "Key1 = " << *Key1 << std::endl;
auto Key2 = *(float*)mymap.get<float>("Key2");
std::cout << "Key2 = " << Key2 << std::endl;
auto Key3 = *(std::string*)mymap.get<std::string>("Key3");
std::cout << "Key3 = " << Key3.data() << std::endl;
Код:
std::vector<int> vVector =
{
1,2,3,4,5,6,7,8,9,0
};
mymap.set<std::vector<int>>("myVector", vVector);
Код:
auto myVector = *(std::vector<int>*)mymap.get<std::vector<int>>("myVector");
std::cout << "myVector:" << std::endl;
for (size_t i = 0; i < myVector.size(); i++)
{
std::cout << " " << myVector[i] << std::endl;
}
Недостаток реализации это необходимость не явной инициализации контейнера, но в данном ключе это не играет большой роли))