Search code examples
c++c++11containersinterface-implementation

How to make my "own" templated map?


I want to implement my own "simple" container which will have map properties but also keeps insertion order. I've heard about boost::multi_index but I find it very difficult to understand for what I want.

So I made a templated class:

template<typename KEY, typename VALUE>
class MyMap {
    private : 
        std::vector<KEY>    m_keys;
        std::vector<VALUE>  m_values;

    public :
        void insert(KEY& key, VALUE& val) {
            //Test if key exists //
            m_keys.push_back(key);
            m_values.push_back(val);
        }

        /* Other methods like erase/size/operator[]/begin/etc. */

};

Just to test it, I wanted to do something like this:

int main() {
    MyMap<string,int> m;
    m.insert("test",1);
    m.insert("cat",2);

    for(auto& item : m) {
        cout << item << endl;
        cout << m[item] << endl;
    }
}

But I keep getting a compilation error on inserts (and [ ]) as it translates my KEY into a basic_string and not a string. It's driving me crazy and I can't find any answer (or any word to properly describe my problem to research for an answer). I guess it has something to do with allocators but I can't manage to understand how to fix it. How can I make my map do this conversion but also stays general as I will need it with other (own-implemented) classes?

EDIT : After solving "string" problem, I had problems when passing int because it was waiting for an &int. Followed kebs advice and implemented a vector> instead and got rid of conversion problems... :)


Solution

  • You can't build a reference from a const char* (even though it gets casted to a string), try this instead:

        template<typename KEY, typename VALUE>
        void insert(KEY key, VALUE val) {
            m_keys.push_back(key);
            m_values.push_back(val);
        }
    

    More precisely, the compiler is pretty clear about the problem:

    error: invalid initialization of non-const reference of type 'std::basic_string&' from an rvalue of type 'std::basic_string' m.insert("test",1);