Artem
Artem

Reputation: 23

How do I insert an element to a set that is a value in multimap C++

I have a trouble with adding a new values to a set<Value_Class> that is in my map<Key, set<Values_Class>>. When I try to add a value like this:

Key key(get<0>(key_args), get<1>(key_args));
        if (!(get<0>(key_args) < 1 && get<0>(key_args) > m_existing_keys_set.size()) && m_existing_keys_set.find(key) != m_existing_keys_set.end())
        {
            Value_Class value(get<0>(value_args), get<1>(value_args), get<2>(value_args));
            set<Value_Class> _temp_set{ value };
            m_map_with_elements.emplace(move(key), move(_temp_set));
        }

There's only the first value I added in the map. The other values just don't insert, there's always only the first added value. Can You help me and tell how should I solve a problem? The whole code:

#pragma once
#include <iostream>
#include <string>
#include <tuple> 
#include <utility>
#include <map>
#include <set>

using namespace std;

class Main_Class
{
private:  //private section for classes and some helper functions
    class Value_Class; struct Key;

    set<Key> m_existing_keys_set
    {
        {1, "Key"}
    }; // all the existing keys will be stored here

    /*----------------------classes start space------------------*/
    /// 
    ///  Value_Class
    /// 
    class Value_Class
    {
    public:

        
    private:
        string m_value_name;
        fouble m_value_double_data;
        bool m_is_available;

    public:
        Value_Class(string val_name, double val_double_data, bool is_avialable) : //Values_Class Constructor
            m_value_name(move(val_name)),
            m_value_double_data(val_double_data),
            m_is_available(is_avialable) {};

        ~Value_Class() {};


        
        friend ostream& operator<<(ostream& os, const Value_Class& dish) {//    Overloading the output << operator
            return os << dish.m_value_name << " >-=-=-=-< Price: " << dish.m_value_double_data;
        }

        bool operator<(const Value_Class& dish) const {//   Overloading the < operator
            return tie(m_value_name, m_value_double_data, m_is_available) < tie(dish.m_value_name, dish.m_value_double_data, dish.m_is_available);
        }

    };

    /// 
    ///  KEY
    /// 
    struct Key
    {
        typedef int dish_number_category_t;
        typedef string dish_name_category_t;
    private:
        dish_number_category_t m_key_number;
        dish_name_category_t m_key_name;
    public:
        Key(dish_number_category_t num, dish_name_category_t str) : // Key constructor
            m_key_number(num),
            m_key_name(move(str)) {};

        bool operator<(const Key& rhs) const {
            return tie(m_key_number, m_key_name) < tie(rhs.m_key_number, rhs.m_key_name);

        }

        friend ostream& operator<<(ostream& os, const Key& k) {
            return os << k.m_key_name;
        }
        bool operator==(const Key& _key) const
        {
            return tie(_key.m_key_number, _key.m_key_name) == tie(m_key_number, m_key_name);
        }
    };

    /*----------------------classes end space------------------*/

    template <class... Args1, class... Args2>
    void add_helper(tuple<Args1...> key_args,
        tuple<Args2...> value_args) // Helper method
    {
        Key key(get<0>(key_args), get<1>(key_args));
        if (!(get<0>(key_args) < 1 && get<0>(key_args) > m_existing_keys_set.size()) && m_existing_keys_set.find(key) != m_existing_keys_set.end())
        {
            Value_Class value(get<0>(value_args), get<1>(value_args), get<2>(value_args));
            set<Value_Class> _temp_set{ value };
            m_map_with_elements.emplace(move(key), move(_temp_set));
        }
    }


public: static Main_Class* get_instance();

private: // private section for all singleton stuff
    Main_Class() {};
    Main_Class(const Main_Class&) = delete;
    Main_Class operator=(const Main_Class&) = delete;

    static Main_Class* _instance; // The only object og the Maim_Class
    map<Key, set<Value_Class>> m_map_with_elements; // the map 

public: // public section for all the public functions
    template <class... Args>
    void add_new_element_to_a_map(Args&&... args)
    {
        add_helper(forward<Args>(args)...);
    }
    
    void print_map() const
    {
        for (auto& itr : m_map_with_elements)
        {
            cout << "Key: " << itr.first << endl;
            for (auto& itr2 : itr.second)
                cout << itr2 << endl;
        }
    }
};
Main_Class* Main_Class::_instance = 0;


Main_Class* Main_Class::get_instance()

{
    if (_instance == 0)
        _instance = new Main_Class();

    return _instance;

} //Singleton access function

Thanks in advance

Upvotes: 0

Views: 178

Answers (1)

Moe
Moe

Reputation: 555

You've assumed that std::map::emplace() will effectively take care of the key duplication while the documentation said that it's not guaranteed.

The element may be constructed even if there already is an element with the key in the container, in which case the newly constructed element will be destroyed immediately.

check out std::map::emplace()

You can use std::map::erase() to erase the item if it exists, then you will get the expected behavior.

template <class... Args1, class... Args2>
void add_helper(tuple<Args1...> key_args,
    tuple<Args2...> value_args) // Helper method
{
    Key key(get<0>(key_args), get<1>(key_args));
    if (!(get<0>(key_args) < 1 && get<0>(key_args) > m_existing_keys_set.size()) && m_existing_keys_set.find(key) != m_existing_keys_set.end())
    {
        Value_Class value(get<0>(value_args), get<1>(value_args), get<2>(value_args));
        set<Value_Class> _temp_set{ value };
        m_map_with_elements.erase(key);
        m_map_with_elements.emplace(move(key), move(_temp_set));
    }
}

You can also provide your own hand-crafted function to handle this.

Upvotes: 1

Related Questions