0

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?

JeJo
  • 30,635
  • 6
  • 49
  • 88
TheCodeNovice
  • 750
  • 14
  • 35
  • I guess you just want `val_map[0] = static_cast(std::stoi(dummy_data[0]));`. The `insert` function takes a map entry (key+value pair) as its insertion argument. – Adrian Mole Oct 18 '22 at 16:23
  • Dupe: [error: no matching function for call to 'std::map](https://stackoverflow.com/questions/31342937/error-no-matching-function-for-call-to-stdmap) – Jason Oct 18 '22 at 16:24
  • Prefer type safe `enum class` to `enum` (in most cases). – Jesper Juhl Oct 18 '22 at 16:33

1 Answers1

2

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?

JeJo
  • 30,635
  • 6
  • 49
  • 88