Cayoot
Cayoot

Reputation: 61

How to overload [] operator to initialize an object

I wanted to implement a class like std::map (just for exercise and learning purposes). I defined my std::map variant like the following one:

template <typename Key, typename Value>
class mmap
{
private:
    std::vector<DATA<Key, Value>> m_maped;
    DATA<Key, Value> m_elements;
    std::mutex m_mutex;
    bool m_repeated_entity = false;

public:
    mmap() {}

    mmap(std::vector<DATA<Key, Value>> arg_mapped)
    {
        for (auto const& pair : arg_mapped)
        {
            push_back(pair.m_key, pair.m_value);
        }
    }

    void push_back(std::vector<DATA<Key, Value>> arg_mapped)
    {
        for (auto const& pair : arg_mapped)
        {
            push_back(pair.m_key, pair.m_value);
        }
    }

    void push_back(Key arg_key, Value arg_value)
    {
        std::lock_guard<std::mutex> guard(m_mutex);

        if (std::none_of(m_maped.begin(), m_maped.end(), [&](auto& it) {return it.m_key == arg_key; }))
        {
            m_elements.m_key = arg_key;
            m_elements.m_value = arg_value;
            m_maped.push_back(m_elements);
        }
    }
}

}

It works fine. I can use the above class like the following one:

mka::container::mmap<int, std::string> g_map_single;
g_map_single.push_back(1, "Jimmy");
g_map_single.push_back(2, "Mimmy");
g_map_single.push_back(2, "Kimmy");

mka::container::mmap<int, std::string> g_map_list;
g_map_list.push_back({ {1, "Jimmy"}, {2, "Kimmy"}, {2, "Limmy"} });

There is no problem till here, but when I wanted to initialize my class like the following, I couldn't:

mka::container::mmap<int, std::string> g_map_init[{ {1, "Jimmy"}, { 2, "Kimmy" }, { 2, "Limmy" } }];
mka::container::mmap<int, std::string> g_map_equal = g_map_list;

The above two code failed to compile. I research and I find out I should overload = and [] operators but I don't know what is the best approach to overload them. I used the following code but all of them didn't work.

void operator[](Key arg_key, Value arg_value)
{
    std::lock_guard<std::mutex> guard(m_mutex);

    if (std::none_of(m_maped.begin(), m_maped.end(), [&](auto& it) {return it.m_key == arg_key; }))
    {
        m_elements.m_key = arg_key;
        m_elements.m_value = arg_value;
        m_maped.push_back(m_elements);
    }
}

How should I fix my code?

Upvotes: 0

Views: 127

Answers (1)

D-RAJ
D-RAJ

Reputation: 3372

What you have there is a std::initializer_list of Key-Value pairs submitted to the index ([]) operator of the mmap class. By default, the compiler doesn't create an overload to the index operator like that, we need to explicitly define it. It may look something like this,

void operator[](const std::initializer_list<DATA<Key, Value>>& list)
{
    for (auto const& pair : list)
        push_back(pair.m_key, pair.m_value);
}

Usually the index operator is used for array indexing or to index a value in a map. Doing it like this is unusual (not meaning that its wrong). As in the comment by @KamilCuk, you can instead use g_map_init{ {stuff here } }. Its more readable and the std::vector has an overloaded constructor to get it done.

Upvotes: 1

Related Questions