adding std::map to init list of ctor - list

I want to add a std::map m_mapName in the initialization list of the constructor.
If I type m_mapName() in the constructor's init list, the compiler accepts it.
But, is it correct?
If it is not correct, how can I add the map to the initialization list?
Then, I do several insertions in the map. What is a more elegant way of inserting values, so I don't call insert function everytime?
More info:
Just like in : C++, can I statically initialize a std::map at compile time?, the compiler doesn't accept syntax like:
std::map<int, char> example = { (1,'a'),
(2, 'b'),
(3, 'c') };
Cannot use Boost.
My code looks like this:
* className.h: *
typedef std::map <uint16_t, int> mapType;
typedef std::pair <uint16_t, int> mapPair;
className{
private:
mapType m_mapName;
}
* className.cpp: *
className::className () :
m_mapName()
{
...
m_mapName.insert(mapPair(someMapValue1, 0));
m_mapName.insert(mapPair(someMapValue2, 0));
m_mapName.insert(mapPair(someMapValue3, 0));

Yes, your code is correct. And the linked question shows what to initialize it with
className::className ()
:m_mapName{
{someMapValue1, 0},
{someMapValue2, 0},
{someMapValue3, 0}}
{}

Related

How to dynamically update members that depend on other members?

Suppose I have a class MyClass:
class MyClass{
private:
vector<vector<float>> _vec;
public:
MyClass(vector<vector<float>> arg){
_vec = arg;
// shape is a 2-element vector where shape[0] = #elems in _vec
// and shape[1] = #elems in _vec[0]
shape.push_back(_vec.size());
shape.push_back(_vec.begin()->size());
}
vector<int> shape;
};
Now suppose I have a member function func of MyClass:
MyClass MyClass::func(){
MyClass res(this->_vec);
// delete the first element of `res._vec`
res._vec.erase(res._vec.begin());
return res;
}
Now, if I do:
MyClass A = {{1, 2}, {3, 4}}; // A.shape[0] = 2, A.shape[1] = 2
MyClass B = A.func(); // B._vec is {{3, 4}} but B.shape[0] is still 2
Here, B._vec changes, but B.shape is not "updated" accordingly.
How can I dynamically update MyClass.shape as and when MyClass._vec changes? One way to do this is to instead make a member function MyClass.shape() which whenever called checks the current MyClass._vec. But is there a better way of doing this?
How can I dynamically update MyClass.shape as and when MyClass._vec changes?
Write a function that updates shape, and call it whenever you change _vec.
But is there a better way of doing this?
Don't use shape member at all, but instead call _vec.size() and _vec.begin()->size() when you need those values. This way there is nothing to update, no redundant duplicate waste of memory, and the user of the class cannot break the apparently missing invariant.

Not able to to do set element insertion inside constructor

I am getting compilation error while inserting values inside constructor Monitor counstructor.
Could you suggest what could be approach for the same as I need to populate this
vector during class instantiation. It works fine with below approach but I don't want to populate the vector separately.
vect1.insert( make_pair(10,20) );
vect1.insert( make_pair(30,49) );
vect1.insert( make_pair(50,60) );
vect1.insert( make_pair(70,80) );
below is the code snippet
#include <iostream>
#include <vector>
#include<algorithm>
#include<memory>
#include <set>
using namespace std;
class Monitor
{
public:
virtual ~Monitor() = default;
explicit Monitor(
const set< pair <double,double> > &vect1
)
{
for (auto &itr : vect1 )
{
std::cout<<"value1 ="<<itr.first<<endl;
std::cout<<"value2="<<itr.second<<endl;
}
}
};
int main()
{ set< pair <double,double> > vect1;
Monitor obj (vect1.insert( make_pair(10,20) ));
return 0;
}
compilation error
error: no matching function for call to ‘Monitor::Monitor(std::pair >, bool>)’
Monitor obj (vect1.insert( make_pair(10,20) ));
You can use constructor of std::set:
Monitor obj({{10,20}, {30,49}, {50,60}, {70,80}});
return type by set::insert is not matching argument of the constructor Monitor(const set< pair <double,double>>&) instead pass the set something like below,
int main()
{
set< pair <double, double> > vect1;
vect1.insert(make_pair(10, 20));
Monitor obj(vect1);
return 0;
}
I wanted to have constructor that recieve a vector that is populated inside the constructor call.
If the vector (or set or whichever) can be a temporary, you can simply create and populate it inside the construction; something as
Monitor obj1{{{10.0, 20.0}, {30.0, 49.0}, {50.0, 60.0}}};
otherwise, if the set must be defined before (as in your example), the solution I see is use the comma operator to populate the set and discard the resulting iterators
std::set<std::pair<double,double>> vect1;
// ..........V <-- observe the parentheses
Monitor obj2{(vect1.insert({10.0, 20.0}), // insert value and discard iterator
vect1.insert({30.0, 49.0}), // insert value and discard iterator
vect1.insert({50.0, 60.0}), // insert value and discard iterator
vect1)}; // pass the populated vect1 to constructor
// ................^ <-- closing parentheses
Monitor obj (vect1.insert( make_pair(10,20) ));
insert returns a std::pair<iterator,bool>, not a std::set<std::pair<double,double>> which is expected by the user defined constructor of Monitor.
According to the user defined Monitor constructor, you need to pass a std::set as an argument. To do so, you can simply pass the std::pair objects to the constructor of std::set:
Monitor obj({{10,20}, {11,21} /*, ...*/});

Moving an std::unordered_map values to std::vector

Is there any way to move unordered_map values to a vector? All the ways I was able to find copy values (like in my example) instead of using something similar to std::move.
I would like to not copy values so I can retain uniqueness of shared_ptr foo, which I'll later change to unique_ptr.
class Class {
public:
std::shared_ptr <int> foo = std::shared_ptr <int> (new int (5));
};
int main() {
std::unordered_map <int, Class> mapOfObjects({
{1, Class()},
{2, Class()},
{3, Class()},
{4, Class()},
{5, Class()} });
std::vector <Class> someVector;
for (auto &object : mapOfObjects) {
someVector.push_back(object.second);
std::cout << "Is unique? " << ( someVector.back().foo.unique() ? "Yes." : "No.")
<< std::endl << std::endl;
}
}
Thank you in advance for all helpful answers.
You can certainly move shared_ptr from unordered_map to vector. All you need to do is to use std::move in your example:
someVector.push_back(std::move(object.second));
Keep in mind, after this operation, you might want to clear the map, as it now contains empty objects.
#SergeyA's answer already covers the essential part here, let me nevertheless add a solution based on range-v3, it shows where one part of the language is heading to with C++20.
#include <range/v3/view/map.hpp>
#include <range/v3/view/move.hpp>
using namespace ranges;
/* Setup mapOfObjects... */
const std::vector<Class> someVector = mapOfObjects | view::values | view::move;
The STL in its current shape isn't that bad either, but admittetly more verbose:
#include <algorithm>
#include <iterator>
std::vector<Class> someVector;
std::transform(std::move_iterator(mapOfObjects.begin()),
std::move_iterator(mapOfObjects.end()),
std::back_inserter(someVector),
[](std::pair<int, Class>&& entry){ return std::move(entry.second); });

populating a static unordered_map local variable

I have a function which makes use of an unordered_map and its only this function in my class which uses it:
void my_func(){
static std::unordered_map<int,int> my_map;
//I only want this to be done the first time the function is called.
my_map[1] = 1;
my_map[2] = 3;
//etc
}
How can I insert the elements in to my static unordered_map so that they only get inserted the first time my function is called (just like the memory allocation is only made the first time)?
Is it possible?
In C++11 (which you're presumably using, otherwise there wouldn't be an unordered_map), containers can be populated by a list initialiser:
static std::unordered_map<int,int> my_map {
{1, 1},
{2, 3},
//etc
};
Historically, the cleanest way would be to call a function that returns a populated container:
static std::unordered_map<int,int> my_map = make_map();

C++ remove_if on a vector of objects

I have a vector (order is important) of objects (lets call them myobj class) where I'm trying to delete multiple objects at a time.
class vectorList
{
vector<*myobj> myList;
};
class myobj
{
char* myName;
int index;
bool m_bMarkedDelete;
}
I was thinking that the best way to do this would be to mark specific myobj objects for deletion and then call myList.remove_if() on the vector. However, I'm not exactly sure how to use predicates and such for this. Should I create a member variable in the object which allows me to say that I want to delete the myobj and then create a predicate which checks to see if the member variable was set?
How do I implement the predicate as a part of the vectorList class?
Should I create a member variable in the object which allows me to say
that I want to delete the myobj and then create a predicate which
checks to see if the member variable was set?
Haven't you already done that? Isn't that what m_bMarkedDelete is for? You would write the predicate like this:
bool IsMarkedToDelete(const myobj & o)
{
return o.m_bMarkedDelete;
}
Then:
myList.erase(
std::remove_if(myList.begin(), myList.end(), IsMarkedToDelete),
myList.end());
Or, using lambdas:
myList.erase(
std::remove_if(myList.begin(), myList.end(),
[](const myobj & o) { return o.m_bMarkedDelete; }),
myList.end());
If your class doesn't actually have that member, and you're asking us if it should, then I would say no. What criteria did you use to decide to mark it for deletion? Use that same criteria in your predicate, for example:
bool IndexGreaterThanTen(const myobj & o)
{
return o.index > 10;
}
note -- The functions I've written are of course invalid since all your members are private. So you'll need some way to access them.
A predicate is basically a conditional comparison. It can be a function or object. Here's an example using new C++ lambdas. This code will go through the vector and remove the values equal to 3.
int arg[6] = {1, 2, 3, 3, 3, 5};
std::vector<int> vec(arg, arg+6);
vec.erase(
std::remove_if(
vec.begin(), vec.end(),
[](int i){ return i == 3;}),
vec.end());
Edit: For pointers let's say you had a vector or interfaces you could set them to nullptr then remove them in a batch with pretty much the same code. In VS2008 you won't have lambdas so make a comparison predicate function or struct instead.
bool ShouldDelete(IAbstractBase* i)
{
return i == nullptr;
// you can put whatever you want here like:
// return i->m_bMarkedDelete;
}
std::vector<IAbstractBase*> vec;
vec.erase(
std::remove_if(
vec.begin(), vec.end(),
ShouldDelete),
vec.end());