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
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.
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} /*, ...*/});
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); });
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();
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());