std::map with structs as values - c++

I have an issue where I need to keep a map of, e.g. vectors, of items, each vector has a corresponding indicator valid for all items for a given key in the map
I guess it could be map of pairs (map<string,pair<vector,bool>>) but that would e very confusing...
So
I wanted to ask you about code like that:
Would this be considered a correct implementation of the problem, is there any potential issue with this? When I add a new key with myMap["KEY"] nothing can ever break because it autoinitializes my struct? Can anything go wrong here?
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct ListOfItemsWithIndicator
{
bool _indicator;
vector<int> _items;
ListOfItemsWithIndicator(): _indicator(false) {}
};
int main() {
std::map<std::string,ListOfItemsWithIndicator> myMap;
myMap["ONE"]._items.push_back(1);
std::cout << myMap["ONE"]._items[0];
return 0;
}

Related

C++ persistence of inserting local variable into a std::map by reference

I'm new to C++ and trying to understand a simple example of inserting a list of integers into a map.
#include <iostream>
#include <map>
#include <list>
using namespace std;
map<string, list<int>> m;
void insert(list<int>& list_to_insert)
{
m.insert({"ABC", list_to_insert});
}
void setup()
{
std::list<int> local_list = { 7, 5, 16, 8 };
insert(local_list);
}
int main()
{
setup();
cout << m["ABC"].size(); // PRINTS 4
}
As far as my understanding, local_list is a variable only known to the setup function. When I pass in a reference to the insert function, I expect it to work. However, at the end of setup, I expect local_list to be removed from the stack frame. However, in my main function, when I call size(), I see that it has in fact persisted throughout. I am not sure I understand how local_list gets persisted at the end of setup(). What is exactly happening here?
map<string, list<int>> m;
contains lists, not references to lists.
So your
m.insert({"ABC", list_to_insert});
will create a copy of the passed list.
PS: why-is-using-namespace-std-considered-bad-practice

Insert custom class with template into std::map

I have written my own class and I want to insert it into a map. See the example below:
#include <iostream>
#include <string>
#include <map>
#include <memory>
#include <mutex>
template <class T>
class A {
public:
T a;
A() = default;
~A() = default;
A(T i) { a = i; }
};
int main()
{
std::pair<int,A<int>> p;
p = std::make_pair<int,A<int>>(9,A<int>(1));
std::map<int, A<int>> m;
m.emplace(1,A<int>(1));
}
When I try to compile this, I get an enormous error. Please help interpret it. :)
See error here:
http://cpp.sh/9nc35
EDIT:
I had the typo, thanks! Though, the other problem I was struggling with first arose now. Seems like it is because of the mutex? Why?
Your map is defined as:
std::map<int, std::unique_ptr<A<int>>>
But in the next line you're trying to pass an std::pair<int, A<int>> to m.emplace() as the key.
I think you just want to do:
m.emplace(9, std::make_unique<A<int>>(1));
// ^
// Not `p`
You are trying to insert/emplace pair (pair<...>, A) into your map, while you've specified it's key as an int. You most-likely want m.emplace(9,std::make_unique<A<int>>(1)); (see 9 instead of p) or just m.insert(p); (would work fine in your cpp.sh).
Furthermore, your use of unique_ptr here is most-likely wrong/unwarranted and only complicates things. See fixed up example here: http://cpp.sh/3d2hw
Also, you may study STL collections/see some basic examples over at https://en.cppreference.com (https://en.cppreference.com/w/cpp/container/map/map for some map construction examples).

how to use push_back in vector of a struct

hey guys i have created a struct node. one of its fields is a vector (path) where i want to store characters.however when i try to push_back a character the compiler says "error: ‘path’ was not declared in this scope"
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
#include <list>
#include <climits>
using namespace std;
struct node {
int weight;
bool pizza; // true an tin exo
vector <char> path;
int tetmimeni, tetagmeni; // i, j gia na vro geitones
} ;
node a;
int main(){
a.tetmimeni=0; // create start node
a.tetagmeni=0;
a.weight=0;
a.pizza=true;
a.path= path.push_back('S');
Replace a.path= path.push_back('S'); with just a.path.push_back('S');
The original code was trying to assign the return type of push_back to a.path which is invalid.
Instead you simply want to invoke the push_back method of the std::vector member of your struct.
In your code , node is a structure. Path is one element of struct.
Anytime you need to access element of struct , you have to use the name of struct along with it.
e.g. a.pizza or a.weight when 'a' is of the type node.
Similarly you need to access a.path when you want to access vector path. It doesn't matter even if you need to call the functions of vector.
You should go through struct/class

Moving elements from std::vector<T1> to std::vector<std::pair<T1,T2>>

What is the most correct and efficient way to std::move elements from a vector of a certain type (T1) into a vector of an std::pair of that same type (T1) and another type (T2)?
In other words, how should I write MoveItems()?
#include <iostream> // For std::string
#include <string> // For std::string
#include <vector> // For std::vector
#include <utility> // For std::pair
using std::vector;
using std::string;
using std::pair;
vector<string> DownloadedItems;
vector<pair<string,bool>> ActiveItems;
vector<string> Download()
{
vector<string> Items {"These","Words","Are","Usually","Downloaded"};
return Items;
}
void MoveItems()
{
for ( size_t i = 0; i < DownloadedItems.size(); ++i )
ActiveItems.push_back( std::pair<string,bool>(DownloadedItems.at(i),true) );
}
int main()
{
DownloadedItems = Download();
MoveItems();
return 0;
}
Thank you for your time and help, I truly appreciate it!
void MoveItems()
{
ActiveItems.reserve(DownloadedItems.size());
for (auto& str : DownloadedItems)
ActiveItems.emplace_back(std::move(str), true);
}
N.B.: For strings as small as the ones in your example, moving may have the same cost as copying due to SSO, or perhaps even slightly more expensive if the implementation decides to empty out the source anyway.
Some things you can do:
At the start of MoveItems(), call ActiveItems.reserve(DownloadedItems.size());. This prevents your array from resizing while you push things into it.
Instead of calling push_back call emplace_back. Here is an explanation of the advantages of doing so.
Worth noting, in this example, you can stop the copy into a new data structure by just constructing the std::pair from the start, and not copying data.

Data structure to store unique <key,value> tuples, where <value> is the minimum

I've to store in a data structures tuples of the type
<(1,1),10>
<(1,1),9>
<(2,1),5>
<(1,1),11>
And I need to have just
<(1,1),9>
<(2,1),5>
Which data structure best fit for this kind of problem in c++?
This is my current solution/workaround, i'll keep looking for a more elegant solution btw.
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <boost/unordered_map.hpp>
#include <boost/foreach.hpp>
using namespace std;
typedef pair<int, int> mapkey;
typedef boost::unordered_map<mapkey,float,boost::hash<mapkey> > hmap;
typedef hmap::iterator hitr;
class mymap
{
public:
hmap map;
void insert(std::pair<mapkey,float> p)
{
hmap::iterator i = map.find(p.first);
if(i==map.end()){
map.insert(p);
}
else{
if(p.second<i->second){
i->second=p.second;
}
}
}
};
int main()
{
mymap map;
map.insert(std::make_pair(mapkey(1,1),10.0f));
map.insert(std::make_pair(mapkey(1,2),22.0f));
map.insert(std::make_pair(mapkey(2,1),22.0f));
map.insert(std::make_pair(mapkey(1,1),5.0f));
BOOST_FOREACH(hmap::value_type i, map.map) {
mapkey m = i.first;
std::cout <<"( "<<m.first<<" , "<< m.second<<" ) > " <<i.second<<endl;
}
return 0;
}
just a simple HashMap will do.
Key- class having two attributes, suppose i, j
value - always minimum i.e. a simple int
A hash table, with a custom insert that inserts iff the key is previously unseen or the new value is less than the previous one.
You can use HashMap build-in class in C++.
For you problem, just a simple customisation that you only need to enter pair in HashMap if
1) Key doesn't exist or
2) If key exists, then compare old-value to new-value and then if new-value is less than old value then insert pair in HashMap.
For your reference you can use Simple HashMap implementation in C++