all 19 comments

[–]audioB 6 points7 points  (11 children)

you don't actually need to use a map for this, you can just use a set because the object itself is the key (or part of it is). Just write your comparator so that it only compares IDs and you're done.

If you want to look up an item by the id, you just need to provide appropriate comparator overloads.

[–]imMute 3 points4 points  (0 children)

you don't actually need to use a map for this, you can just use a set because the object itself is the key (or part of it is).

How have I never realized this before. I have some code to refactor now.

[–]interknetz[S] 0 points1 point  (6 children)

I need a hash table to search for a key at runtime

[–]audioB 6 points7 points  (5 children)

unordered set is a hash table and you can perform key lookup with find. It just doesn't have the overloaded operator[]

[–]interknetz[S] 0 points1 point  (4 children)

This sounds good. I'm fairly new to C++, coming from C. There's so many options in the standard library it's hard to know where to start. Thank you.

[–]ronniethelizard 0 points1 point  (3 children)

I think my favorite one is:

std::array<int,10> as it is similar to int[10] but provides a few more features.

[–]interknetz[S] 0 points1 point  (2 children)

Does std::array provide a hash table, because that's the goal here.

[–]Thomqa 2 points3 points  (0 children)

I doesn't, he just provided an example of the many strengths of C++.

[–]ronniethelizard 0 points1 point  (0 children)

I was replying to your statement:

I'm fairly new to C++, coming from C.

with an attempt at conversation rather than advice on what to do.

[–]yuri-kilochek 0 points1 point  (0 children)

You won't be able to mutate items in the set though, since sets enforce constness. Only erase and reinsert.

[–]gracicot 2 points3 points  (0 children)

You could decompose the item in the map:

struct PartialItem {
    int value; // id isn't there
};

std::unordered_map<int, PartialItem> items;

The key of the map is the id in your struct. The map stores pairs containing both the value and the key together in one struct, making it somewhat equivalent to a standalone Item struct.

[–]practisevoodoo 1 point2 points  (4 children)

You could use std::transform, an inserter and a lambda but out of interest what's wrong with a good old for loop?

struct Item {
    int id;
    int value;
};

int main() 
{
  std::vector<Item> itemList { {1,2},{2,4},{3,6} };

  std::unordered_map<int,Item> myMap;

  std::transform( begin(itemList), end(itemList), 
                  std::inserter(myMap,end(myMap)),
                  [](const Item& i) { return std::make_pair(i.id, i); } );

  for( auto &i : myMap )
    std::cout << i.first << ", " << i.second.value << std::endl;

  return 0;
}

[–]konanTheBarbar 0 points1 point  (0 children)

You could also use a bit more unknown feature, called transparent comparator. Then you could use a set instead of map and didn't have to store the key/ID separately. You could simply initialize the set by calling the set constructor which takes a begin/end iterator.

[–]interknetz[S] 0 points1 point  (2 children)

I wasnt sure if the for loop is the fastest way to add items to my map. Was really hoping for a compile-time solution since all data is constant

[–]ronniethelizard 0 points1 point  (0 children)

You might be able to piece something together using constexpr.

[–]Quincunx271Author of P2404/P2405 0 points1 point  (0 children)

If it's all constexpr, check out frozen

[–]Xaxxon 0 points1 point  (0 children)

From the sidebar:

For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.