Std::map. Упрощаем немного себе жизнь

Эксперт
Статус
Оффлайн
Регистрация
12 Июн 2014
Сообщения
991
Реакции[?]
1,209
Поинты[?]
3K
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;
    }
};
как видим код совсем не сложный. Описан только необходимый, на данный момент, функционал: запись значения и получения значения по ключу. Так сказать "Minimalistic Style". Многое не учтено, но и этого достаточно на первых парах.

Теперь поговорим о практическом применении:
для начала простой пример использования. Заполняем данные:
Код:
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;

    }



Недостаток реализации это необходимость не явной инициализации контейнера, но в данном ключе это не играет большой роли))
 
Похожие темы
Ответы
4
Просмотры
2K
Сверху Снизу