populating a static unordered_map local variable - c++

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();

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.

Using a temporary object without storing it in variable

Let's take an example where we need to insert the vector returned from a function to another vector:
const std::vector<int> getvec(){
return {1, 2, 3};
}
// in main...
std::vector<int> foo{ 11, 12 };
auto bar = getvec();
foo.insert(foo.end(), bar.begin(), bar.end());
The fact that the bar variable needs to be referenced twice in the insert() method makes it necessary to have the vector stored as a variable (we could otherwise do foo.myinsert(getvec()) should there be such an interface).
It is a bit annoying to me that in such a case, we need to introduce a variable foo in the main scope which is not meant to be used again in the rest of the code, as it occupies the memory and also pollutes the namespace. Especially a problem if we are talking about with a large "temporary" object.
Is there a standard approach to deal with that? We could define a function that take the "temporary" object only once so that we can directly feed function output to it, but would be difficult to manage if we need to define such function for every similar scenario. Also as in this example we are not able to define a member function for vector class.
Alternatively what using braces to limit the scope of the "temporary" part of the insertion but I would like to know if any caveat here.
vector<int> foo{ 11, 12 };
{ // extra brace here
auto bar = getvec();
foo.insert(foo.end(), bar.begin(), bar.end());
} // extra brace here
Not the prettiest solution, but you could use a temporary lambda instead of a separate function, and declaring and invoking it in the same statement avoids the need for braces to limit its scope.
const std::vector<int> getvec(){
return {1, 2, 3};
}
// in main...
std::vector<int> foo{ 11, 12 };
[&](const auto &bar){ foo.insert(foo.end(), bar.begin(), bar.end()); }(getvec());
Live Demo
You could write a little template function to do this, which takes a vector by const reference (which can bind to a temporary and extend its lifetime):
template<typename C>
void append(std::vector<C> &invec, const std::vector<C> &temp)
{
invec.insert(std::end(invec), std::begin(temp), std::end(temp));
}
and this could be used for all other types of vectors. Then you can call it like this:
append(foo, getvec());
Working demo here.
You can make strings of other things than char. Thru basic_string<int> you can access string::append ( and other things )
using strint = std::basic_string<int>;
strint getVec () {
return { 1, 2, 3, 4, 5 };
}
strint foo{ 6, 7 };
foo += getVec();
https://godbolt.org/z/h4naTa

adding std::map to init list of ctor

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}}
{}

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());

Initialisation of static vector

I wonder if there is the "nicer" way of initialising a static vector than below?
class Foo
{
static std::vector<int> MyVector;
Foo()
{
if (MyVector.empty())
{
MyVector.push_back(4);
MyVector.push_back(17);
MyVector.push_back(20);
}
}
}
It's an example code :)
The values in push_back() are declared independly; not in array or something.
Edit: if it isn't possible, tell me that also :)
In C++03, the easiest way was to use a factory function:
std::vector<int> MakeVector()
{
std::vector v;
v.push_back(4);
v.push_back(17);
v.push_back(20);
return v;
}
std::vector Foo::MyVector = MakeVector(); // can be const if you like
"Return value optimisation" should mean that the array is filled in place, and not copied, if that is a concern. Alternatively, you could initialise from an array:
int a[] = {4,17,20};
std::vector Foo::MyVector(a, a + (sizeof a / sizeof a[0]));
If you don't mind using a non-standard library, you can use Boost.Assignment:
#include <boost/assign/list_of.hpp>
std::vector Foo::MyVector = boost::list_of(4,17,20);
In C++11 or later, you can use brace-initialisation:
std::vector Foo::MyVector = {4,17,20};
With C++11:
//The static keyword is only used with the declaration of a static member,
//inside the class definition, not with the definition of that static member:
std::vector<int> Foo::MyVector = {4, 17, 20};
Typically, I have a class for constructing containers that I use (like this one from boost), such that you can do:
const list<int> primes = list_of(2)(3)(5)(7)(11);
That way, you can make the static const as well, to avoid accidental modifications.
For a static, you could define this in the .cc file:
// Foo.h
class Foo {
static const vector<int> something;
}
// Foo.cc
const vector<int> Foo::something = list_of(3)(5);
In C++Ox, we'll have a language mechanism to do this, using initializer lists, so you could just do:
const vector<int> primes({2, 3, 5, 7, 11});
See here.
You could try this one:
int arr[] = { 1,2,3,4,5,6,7,8,9 };
MyVector.insert(MyVector.begin(), arr, &arr[sizeof(arr)/ sizeof(*arr)]);
But it's probably only worth when you have a really long vector, and it doesn't look much nicer, either. However, you get rid of the repeated push_back() calls. Of course, if your values are "not in an array" you'd have to put them into there first, but you'd be able to do that statically (or at least references/pointers), depending on the context.
How about initializing using a static object. In its constuctor it
could call a static function in the object to do the initalization.
with boost you can use the +=() operator defined in the boost::assign namespace.
#include <boost/assign.hpp>
using namespace boost::assign;
int main()
{
static std::vector<int> MyVector;
MyVector += 4,17,20;
return 0;
}
or with static initialization:
#include <boost/assign.hpp>
using namespace boost::assign;
static std::vector<int> myVector = list_of(4)(17)(2);
int main()
{
return 0;
}
or even better, if your compiler supports C++ 11, use initialization lists.