I have a vector with each element being a pair. I am confused with the syntax. Can someone please tell me how to iterate over each vector and in turn each element of pair to access the class.
std::vector<std::pair<MyClass *, MyClass *>> VectorOfPairs;
Also, please note, I will be passing the values in between the function, hence VectorOfPairs with be passed by pointer that is *VectorOfPairs in some places of my code.
Appreciate your help. Thanks
This should work (assuming you have a C++11 compatible compiler)
for ( auto it = VectorOfPairs.begin(); it != VectorOfPairs.end(); it++ )
{
// To get hold of the class pointers:
auto pClass1 = it->first;
auto pClass2 = it->second;
}
If you don't have auto you'll have to use std::vector<std::pair<MyClass *, MyClass *>>::iterator instead.
Here is a sample. Note I'm using a typedef to alias that long, ugly typename:
typedef std::vector<std::pair<MyClass*, MyClass*> > MyClassPairs;
for( MyClassPairs::iterator it = VectorOfPairs.begin(); it != VectorOfPairs.end(); ++it )
{
MyClass* p_a = it->first;
MyClass* p_b = it->second;
}
Yet another option if you have a C++11 compliant compiler is using range based for loops
for( auto const& v : VectorOfPairs ) {
// v is a reference to a vector element
v.first->foo();
v.second->bar();
}
You can access the elements of pairs inside vector in C++17 in a following style by combining range-based for loop and structured bindings. Example:
for (auto& [x, y] : pts) {
cin >> x >> y;
}
where pts is a vector of pairs. & is used to make formal "uniquely-named variable" e of structured binding a reference so that x and y referring to subobjects of e refer to original pair inside pts, which can be modified this way (e.g. cin can be used to input to it). Without &, e would be a copy (to subobjects of which x and y again refer). Example using your VectorOfPairs:
for (auto [pFirst, pSecond] : VectorOfPairs ) {
// ...
}
Also you can make e a reference to const when modification through structured binding is not needed and you want to avoid potentially expensive copy of a pair (though this should not be a problem in your case since pair object consisting of 2 pointers is pretty small and cheap to copy). Example:
for (const auto& [pFirst, pSecond] : VectorOfPairs ) {
// ...
}
Related
Say that I have a vector, v,
vector <int> v = {0,1,2,...n};
What is the proper way to loop through v in a function taking a pointer to v as an argument? I can see two ways, either dereference the vector using (*) or using the .at() member:
void foo(vector <int>* v)
{
for (auto& el : (*v))
bar(el);
}
or
void foo(vector <int>* v)
{
for (int k = 0; k < n; k++)
bar(v->at(k));
}
Is there any difference between the two? Or is there another, superior, way to do it? It seems to me the second one would dereference the full vector object each iteration to get a single value, which seems like a bit of an over-kill, surely it would be better to only dereference the value at the memory location you want?
Pointer will be dereferenced in both cases. However at performs range checking and throws an exception if it fails so second approach will be slower.
A proper approach may look like this:
void foo(::std::vector<int> & v)
{
for(auto & el: v)
{
bar(el);
}
}
Since your code assumes that pointer is always valid there is not a single reason to use it instead of a reference. See Cpp Core Guidelines.
I have C++ code with a type auto:
auto T = reads a JSON
I need to print the content of the T using
cout << T << endl;
It is not working. Can you help me?
With C++11, you can declare a variable or an object without specifying its specific type by using auto.1 For example:
auto i = 42; // i has type int
double f();
auto d = f(); // d has type double
The type of a variable declared with auto is deduced from its initializer. Thus, an initialization is required:
auto i; // ERROR: can’t dedulce the type of i
Additional qualifiers are allowed. For example:
static auto vat = 0.19;
Using auto is especially useful where the type is a pretty long and/or complicated expression. For example:
vector<string> v; ... auto pos = v.begin(); // pos has type vector<string>::iterator
auto l = [] (int x) -> bool { // l has the type of a lambda ..., // taking an int and returning a bool };
In short auto can deduce any type .Your program is not working because it is possible that it is not able to parse JSON or compiler is old (where auto is not supported .Can you specifically let me know the error you got ?
auto in C++ means "set variable type for type of initialization expression", in your case whatever that "reads a JSON" expression returns. You cannot output that type to std::cout because operator<< is not defined for such type, there could be many possible reasons as operator not provided, you suppose to use something else, missing header etc. Solution would depend on actual type.
Ok ! Before telling you how to use auto, I must tell you it's one of the best features of C++11 & has made C++ even more efficient by :-
Reducing amount of code
Enforcing initialization
Increasing genericity (In C++17)
Firstly auto has only 1 job. It will deduce the type of an object by the value passed to it. For ex :-
auto x = 5;
This means that x is an integer whose value is 5. Whenever you are using auto you must initialize the variable (which is a good thing) & you cannot use auto on multiple types in a statement. For ex :-
auto x; // illegal ! x isn't initialized so compiler cannot dduce it's type
auto z=5, y=7; // legal because z & y are both integers
auto a=8, ch= 'c'; // illegal ! an integer & a character in a single statement, hence type deduction ambiguity
The cream of auto is not in intializing int, char, etc data types. It's more handy for classes like iterators. For ex :-
vector<int> v;
vector<int>::iterator i1 = v.begin();
auto i2 = v.begin(); // see how auto reduces the code length
This can be even more obvious in for loops :-
for (vector<int>::iterator i = v.begin(); i!=v.end(); ++i);
Can be reduced to :-
for (auto i = v.begin(), i!=v.end(); ++i);
If you are not happy with the above then this may inspire you to use auto :-
vector< map <int, vector<string> > >::iterator i1 = v.begin(); // where v is the vector of maps of ints & vectors of strings !!!!
auto i2 = v.begin();
The genericity I was talking about is in passing values to functions by auto. Like :-
void add (auto x, auto y)
{
cout << x+y << '\n';
}
This is not possible in current standards & has been proposed for C++17. This is likely to increase the generic ability of the functions without the use of templates. However this syntax is possible for lambda functions :-
auto l = [](auto x, auto y) { return x+y; } // legal from C++14 onwards
However be careful when using braces with lambda because you may think that :-
auto x = {5};
Is an integer but it is actually an intializer_list<int> type object. I can explain a hell lot about auto but I guess for now this is more than enough.
This is a piece of code I'm currently using and I was wondering if there was a more elegant way of doing this in C++11 -
Essentially vector_a is copied to vector_b, then slightly modified, then vector_b is returned.
Vector elements are of class Point which is basically (leaving out constructors and a bunch of methods):
class Point {
double x,
y,
z;
};
Ideally I'd love to boil down the assignment of member z from vector_a to vector_b to something like a line or two but couldn't come up with an elegant way of doing it.
Any suggestions welcome!
auto localIter = vector_a.begin();
auto outIter = vector_b.begin();
while (localIter != vector_a.end() && outIter != vector_b.end())
{
outIter->z = localIter->z;
localIter++;
outIter++;
}
You may use transform().
std::transform (vector_a.begin(), vector_a.end(), vector_b.begin(), vector_a.begin(), [](Elem a, Elem b) { a->z = b->z; return a; });
Where Elem is a type of vector element.
As the vector has a random access iterator (using of std::next is effective) then I would write the code the following way
auto it = vector_a.begin();
std::for_each( vector_b.begin(),
std::next( vector_b.begin(),
std::min( vector_a.size(), vector_b.size() ) ),
[&it] ( Point &p ) { p.z = it++->z; } );
A partial copy is, actually, just a transformation of the elements (one of many), and therefore std::transform is a natural fit here.
Like many algorithms acting on multiple sequences, you have to be careful about the bounds of your containers; in this particular case, since vector_b just receives stuff, the easiest is to start empty and adjust its size as you go.
Thus, in the end, we get:
vector_b.clear();
std::transform(vector_a.begin(),
vector_a.end(),
std::back_inserter(vector_b),
[](Elem const& a) { Elem b; b.z = a.z; return b; });
transform is perhaps the most generic algorithm in the Standard Library (it could imitate copy for example), so you should carefully consider whereas a more specialized algorithm exists before reaching for it. In this case, however, it just fits.
I would be tempted to do something a bit like this:
#include <vector>
struct info
{
int z;
};
int main()
{
std::vector<info> a = {{1}, {2}, {3}};
std::vector<info> b = {{4}, {5}};
for(size_t i(0); i < a.size() && i < b.size(); ++i)
b[i].z = a[i].z;
}
The book i am reading offers this example when iterating over a vector
for (auto &e: v) {
cout << e << endl;
}
Suppose v is declared as vector<int> v, in other words, we know that the type of elements inside this collection is int.
Is using auto in any way better or preferred to?
for (int &e: v) {
cout << e << endl;
}
Why?
Yes. auto is preferred. Because if you change the declaration ofv from:
std::vector<int> v; //before
to this:
std::vector<float> v; //after
If you use int & in the for, then you have to change that as well. But with auto, no need to change!
In my opinion, working with auto is more or less like programming to interface. So if you do an operation += in the loop, and you don't really care about the type of the loop variable e as long as the type supports += operation, then auto is the solution:
for(auto & e : v)
{
e += 2;
}
In this example, all you care about that the type of e supports += with int on the right hand side. It will work even for user-defined types, which has defined operator+=(int), or operator+=(T) where T is a type which supports implicit conversion from int . It is as if you're programming to interface:
std::vector<Animal*> animals;
animals.push_back(new Dog());
animals.push_back(new Cat());
animals.push_back(new Horse());
for(size_t i = 0 ; i < animals.size(); ++i)
{
animals[i]->eat(food); //program to interface
}
Of course, you would like to write this loop as:
for(Animal * animal : animals)
{
animal->eat(food); //still program to interface
}
Or simply this:
for(auto animal : animals)
{
animal->eat(food); //still program to interface
}
It is still programming to interface.
But at the same time, the point in #David's comment is worth noting.
On your first example, you have less dependency on what the elements of the vector are.
Suppose that in a month, you require that your vector stores larger integers, so you will have to use an std::vector<int64_t>, or some other, wider type. Now all of the code that iterates over that vector is invalid. You'll have to modify each:
for (int &e: v) {}
For a:
for (int64_t &e: v) {}
That is why it's better to just let auto deduce the internal type. That way you can modify the type stored in your vector for another, compatible one, and all your code will still work.
I recently hit a problem and the only way I can see to avoid it is to use const_cast - but I'm guessing there is a way I'm not thinking of to avoid this without otherwise changing the function of the code. The code snippet below distills my problem into a very simple example.
struct Nu
{
Nu() {v = rand();}
int v;
};
struct G
{
~G()
{
for(auto it = _m.begin(); it != _m.end(); it++) delete it->first;
}
void AddNewNu()
{
_m[new Nu] = 0.5f;
}
void ModifyAllNu()
{
for(auto it = _m.begin(); it != _m.end(); it++) it->first->v++;
}
float F(const Nu *n) const
{
auto it = _m.find(n);
// maybe do other stuff with it
return it->second;
}
map<Nu*, float> _m;
};
Here, suppose Nu is actually a very large struct whose layout is already fixed by the need to match an external library (and thus the "float" can't simply be folded into Nu, and for various other reasons it can't be map<Nu, float>). The G struct has a map that it uses to hold all the Nu's it creates (and ultimately to delete them all on destruction). As written, the function F will not compile - it cannot cast (const Nu *n) to (Nu n) as expected by std::map. However, the map can't be switched to map<const Nu*, float> because some non-const functions still need to modify the Nu's inside _m. Of course, I could alternatively store all these Nu's in an additional std::vector and then switch the map type to be const - but this introduces a vector that should be entirely unnecessary. So the only alternative I've thought of at the moment is to use const_cast inside the F function (which should be a safe const_cast) and I'm wondering if this is avoidable.
After a bit more hunting this exact same problem has already been addressed here: Calling map::find with a const argument
This is because the map expects Nu* const, but you have given it a const Nu*. I also find it highly illogical and don't understand why, but this is how it is.
"find" in your case will return a const_iterator. putting:
map<Nu*,float>::const_iterator it = _m.find(n);
...
return it->second;
should work I think.
Since you are in a const method you can only read your map of course, not write/modify it