Search code examples
c++algorithmenumsinsertstdmap

Cannot insert a enum type into a map


I am a novice at C++, but I am trying to build a std::map that has an enum type as value, to avoid fussing with strings.

I have created a minimum example below which does not work

#include <iostream>
#include <fstream>
#include <map> 
#include <vector>

enum val_list {Foo, Bar}; 

int main()
{
    std::map<int, val_list> val_map;
    std::vector<std::string> dummy_data = {"0","1","3"};
    
    val_map.insert(0,static_cast<val_list>(std::stoi(dummy_data[0])));  
}

I get the following compiler error

test.cc:17:66: error: no matching function for call to 
  ‘std::map<int, val_list>::insert(int, val_list)’
   17 |  val_map.insert(0,static_cast<val_list>(std::stoi(dummy_data[0])));

This toy example is similar to my actual program, which gives me a slightly different error with the same structure

enum PhysicalNames {unassigned,top_points,
  side_points, bottom_points, top_lines, 
  side_lines, bottom_lines, symetry_line, 
  top_surface,side_surface,bottom_surface};

std::vector<std::string> entity_data;
std::map<int, PhysicalNames> node_map;

node_map.insert(std::stoi(entity_data[0]),group);

This gives me the same error but with a reference variable which is weird

error: no matching function for call to 
       ‘std::map<int, PhysicalNames>::insert(int, PhysicalNames&)’
  284 |             node_map.insert(std::stoi(entity_data[0]),group);

What am I doing wrong, exactly?


Solution

  • You are using the std::map::insert wrong!

    The std::map::insert expect a std::map::value_type (i.e std::pair<const Key, T>) as argument there, not the key and value. In your first example, this is std::pair<const int, val_list>.

    From cppreference.com overloads (1) and (3):

    std::pair<iterator, bool> insert( const value_type& value ); (1)
    //                                ^^^^^^^^^^^^^^^^^^^^^^^^
    std::pair<iterator, bool> insert( value_type&& value );  (3)    (since C++17)
    //                                ^^^^^^^^^^^^^^^^^^
    

    That means you need extra {} there, so that value_type be constructed on the go:

    val_map.insert({ 0, static_cast<val_list>(std::stoi(dummy_data[0])) });
    //            ^^^                                                  ^^^ 
    

    Alternatively, mention the value_type while passing

    val_map.insert(std::pair<const int, val_list>{
          0, static_cast<val_list>(std::stoi(dummy_data[0])) 
    });
    

    or std::make_pair while passing

    val_map.insert(std::make_pair(
           0, static_cast<val_list>(std::stoi(dummy_data[0])) 
    ));
    

    This could have been avoided if you have used std::map::emplace. As a plus, the map entry will be constructed in place in the map.

    val_map.emplace(0, static_cast<val_list>(std::stoi(dummy_data[0])) );
    

    As a side note, use enum struct or enum class, which provids type safety over the plane enums. Read more: Why is enum class preferred over plain enum?