STL template function to return a pair - c++

I'm trying to write a function that returns a pair of values from an STL container.
template <typename T>
std::pair<typename T::value_type,typename T::value_type> getMinMax(T &container) {
auto min = *(container.begin());
auto max = *(container.begin());
for (auto it : container) {
if (min > (*it) ) {
min = (*it);
}
if (max < (*it) ) {
max = (*it);
}
}
return std::make_pair(min, max);
};
int main() {
std::vector<int> c{1, 2, 3, 4, 5};
auto p = getMinMax(c);
std::cout << "min: " << p.first << " max: " << p.second << "\n";
}
I'm getting an error:
error: indirection requires pointer operand ('int' invalid)
if (min > (*it) ) {
I don't know how to deal with that.
Besides that error, is there a better way to implement the desired behavior?

for range returns element, not iterator. So your loop should be something like:
for (const auto& e : container) {
if (min > e) {
min = e;
}
if (max < e) {
max = e;
}
}

template <typename T>
std::pair<typename T::value_type, typename T::value_type> getMinMax(T &container) {
auto min = *(container.begin());
auto max = *(container.begin());
for (const auto& element : container) { /* ERROR WAS HERE, FOR RANGE LOOPS RETURN AN ELEMENT */
if (min > element) {
min = element;
}
if (max < element) {
max = element;
}
}
return std::make_pair(min, max);
};
Hey! This should work, you were setting min and max to a dereferenced element, which of course, isn't what we want. :)
Also, you can get undefined behavior with this, for example, if the container was empty. Perhaps you should add some checks that check for that.

For starters the function can have undefined behavior in case when the container is empty because there can be an attempt of dereferencing the iterator of an empty container.
In loops like this
for (auto it : container) {
if (min > (*it) ) {
min = (*it);
}
there is incorrectly used dereferencing.
You could use the standard algorithm std::minmax_element. However it does not do the same as your code. It returns the first minimum element and the last maximum element. So you should rewrite the algorithm std::minmax_element such a way that ir would return the first minimum element (the iterator pointing to the first minimum element) and the first maximum element (the iterator pointing to the first maximum element).
The function can be defined for example the following way
#include <iostream>
#include <utility>
#include <vector>
#include <iterator>
template <typename T>
auto getMinMax( T &container )
-> std::pair<decltype( container.begin() ), decltype( container.begin() )>
{
auto min = container.begin();
auto max = container.begin();
if ( !container.empty() )
{
for ( auto it = container.begin(); ++it != container.end(); )
{
if ( *it < *min ) min = it;
else if ( *max < *it ) max = it;
}
}
return { min, max };
}
int main()
{
std::vector<int> v = { 5, 2, 3, 7, 1, 4, 9, 8, 6 };
auto minmax = getMinMax( v );
std::cout << "Minimum = " << *minmax.first
<< " at position " << std::distance( v.begin(), minmax.first )
<< " and maximum = " << *minmax.second
<< " at position " << std::distance( v.begin(), minmax.second )
<< std::endl;
return 0;
}
The program output is
Minimum = 1 at position 4 and maximum = 9 at position 6

Related

C++ set: find & delete elements based on customized comparator

In my program, set has elements of type pair<char, double>. I also implemented the logic so that set is sorted based on element's 2nd value, from smallest to largest:
using pair_item = std::pair<char, double>;
std::set<pair_item, decltype([](auto e1, auto e2){return e1.second < e2.second;})> pq;
Now, I want to delete an element from set, based on element's 1st value:
auto first_is_w = std::lower_bound(
pq.begin(), pq.end(), [w](const auto& p) {
return p.first == w;
}
);
if (first_is_w != pq.end() && first_is_w->first == w) {
pq.erase(first_is_w);
}
Unfortunately, I got error:
'const A_star(const std::vector<std::tuple<char, char, double> >&, std::unordered_map<char, double>&, char, char)::<lambda(const auto:13&)>' is not derived from 'const std::optional<_Tp>'
{ return *__it < __val; }
~~~~~~^~~~~~~
I'm wondering how should I modify my lambda function to run the search correctly?
Full codes attached below:
#include <iostream>
#include <set>
#include <utility>
using pair_item = std::pair<char, double>;
void printSet(const auto& pq) {
std::cout << "Current pq:" << std::endl;
for (const auto& ele : pq) {
std::cout << "(" << ele.first << ", " << ele.second << "), ";
}
std::cout << std::endl;
}
int main() {
char w = 'A';
std::set<pair_item, decltype([](auto e1, auto e2){return e1.second < e2.second;})> pq;
pq.emplace('A', 30);
pq.emplace('B', 20);
pq.emplace('C', 10);
printSet(pq);
auto first_is_w = std::lower_bound(
pq.begin(), pq.end(), [w](const auto& p) {
return p.first == w;
}
);
if (first_is_w != pq.end() && first_is_w->first == w) {
pq.erase(first_is_w);
}
return 0;
}
Your lambda is fine, but you're using the wrong algorithm. lower_bound requires a sorted range and strict weak ordering comparison, which you do not have for the value you're looking for.
You should use std::find_if, which is an O(N) linear search.
auto first_is_w = std::find_if(
pq.begin(), pq.end(), [w](const auto& p) {
return p.first == w;
}
);
if (first_is_w != pq.end()) {
pq.erase(first_is_w);
}

Writing a custom insert function for std::vector

I was writing the insert function for std::vector for my personal project.
Vector layout before insert:
position : 0 1 2 3 4
Value : a b c e f
Assuming there is enough capacity, I want to insert 'd' at position 3.
Vector layout after insert:
position : 0 1 2 3 4 5
Value : a b c d e f
I wrote a function to shift the values to the right after the given insert position (in the example it is 3) and then I assign the given value at the requested insert position.
The function I wrote to shift_right is as follows:
template <typename T>
void vector<T>::shift_right(typename vector<T>::iterator given_pos) {
for (auto iter = end() - 1; iter != given_pos - 1; iter--) {
*(iter + 1) = *iter;
}
}
Is there a std::algorithm, or variation of it that can help me get rid of my raw loop in the shift_right function?
You can use std::move_backward:
template< class BidirIt1, class BidirIt2 ><br>
BidirIt2 move_backward( BidirIt1 first, BidirIt1 last, BidirIt2 d_last );
Moves the elements from the range [first, last), to another range ending at d_last. The elements are moved in reverse order (the last element is moved first), but their relative order is preserved.
So your code might look like this (not tested):
template <typename T>
void vector<T>::shift_right(typename vector<T>::iterator given_pos) {
std::move_backward(given_pos, end()-2, end()-1);
}
This assumes that the capacity has already been increased if necessary and that end() returns the new end iterator (i.e. one past the last element after the new space was inserted). Change to std::move_backward(given_pos, end()-1, end()); if that's not the case.
It seems you mean something like the following
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
template <typename T>
typename std::vector<T>::iterator
shift_right( std::vector<T> &v, typename std::vector<T>::size_type pos )
{
v.resize( v.size() + 1 );
typename std::vector<T>::iterator result = std::end( v );
if ( pos < v.size() )
{
result = std::copy_backward( std::next( std::begin( v ), pos ),
std::prev( std::end( v )),
std::end( v ) );
}
return std::prev( result );
}
int main()
{
std::vector<int> v;
auto it = shift_right( v, v.size( ) );
*it = 2;
for ( const auto &item : v ) std::cout << item << ' ';
std::cout <<'\n';
it = shift_right( v, v.size() );
*it = 3;
for ( const auto &item : v ) std::cout << item << ' ';
std::cout <<'\n';
it = shift_right( v, 0 );
*it = 0;
for ( const auto &item : v ) std::cout << item << ' ';
std::cout <<'\n';
it = shift_right( v, 1 );
*it = 1;
for ( const auto &item : v ) std::cout << item << ' ';
std::cout <<'\n';
return 0;
}
The program output is
2
2 3
0 2 3
0 1 2 3
Pay attention to that it is better to use std::copy_backward instead of std::move_backward because in the first case the state of all elements of the vector will be consistent similarly to elements of an array of fundamental types after shifting them.
If to use std::move_backward then the corresponding function can look the following way as it is shown in the demonstrative program below.
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
template <typename T>
typename std::vector<T>::iterator
shift_right( std::vector<T> &v, typename std::vector<T>::size_type pos )
{
v.resize( v.size() + 1 );
typename std::vector<T>::iterator result = std::end( v );
if ( pos < v.size() )
{
result = std::move_backward( std::next( std::begin( v ), pos ),
std::prev( std::end( v )),
std::end( v ) );
}
result = std::prev( result );
*result = T();
return result;
}
int main()
{
std::vector<int> v = { 1, 2, 4, 5, 6 };
for ( const auto &item : v ) std::cout << item << ' ';
std::cout <<'\n';
auto it = shift_right( v, 2 );
for ( const auto &item : v ) std::cout << item << ' ';
std::cout <<'\n';
*it = 3;
for ( const auto &item : v ) std::cout << item << ' ';
std::cout <<'\n';
return 0;
}
The program output is
1 2 4 5 6
1 2 0 4 5 6
1 2 3 4 5 6
I would first define a convenience function template, right_shift_by_one(), that shifts the elements to the right by one position in the valid iterator range [first, last):
template<typename BidirIt>
void right_shift_by_one(BidirIt first, BidirIt last) {
std::move_backward(first, std::prev(last), last);
}
Then, your custom vector's member function, shift_right(), which eventually calls the convenience function defined above:
template<typename T>
auto shift_right(typename vector<T>::iterator pos) {
auto dist = std::distance(begin(), pos);
// this only compiles if T is default constructible
resize(size()+1);
// resize() may have invalidated the pos iterator due to vector's reallocation
// recompute it
pos = begin() + dist;
right_shift_by_one(pos, end());
return pos;
}
This member function returns an iterator pointing to the element corresponding to the new space created by right shifting. This works even if the vector doesn't have enough capacity because the invalidation of iterators on reallocation has been taken into account. You have to implement resize() in your custom vector implementation, though.
Use:
auto it = shift_right(vec.begin() + 2);
*it = 'c';

Check std::vector has duplicates

I want to check if a vector of integers has any duplicates or not, and have to return true if it does. So I try to do something like this:
vector<int> uGuess = {1,2,3,3,4,5}
vector<int> a = uGuess;
sort(a.begin(), a.end());
bool d = unique(a.begin(), a.end());
And this will not work since unqiue cannot be assigned as a bool value.
How should I proceed towards this?
If I were to write a for loop to perform the same action, how should I do that?
The algorithm you're looking for is std::adjacent_find.
// The container must be sorted!
const std::vector<int> sortedVector = {1,2,3,3,4,5};
const bool hasDuplicates = std::adjacent_find(sortedVector.begin(), sortedVector.end()) != sortedVector.end();
Unlike std::unique, std::adjacent_find doesn't modify the container.
As a bonus, std::adjacent_find returns an iterator to the first element in the duplicate "pair":
const auto duplicate = std::adjacent_find(sortedVector.begin(), sortedVector.end());
if (duplicate != sortedVector.end())
std::cout << "Duplicate element = " << *duplicate << "\n";
Looking at google for std::unique I found this page std::unique. I looked at what it did:
Eliminates all except the first element from every consecutive group of equivalent elements from the range [first, last)
So it looks like it does what you want - removes the duplicates.
I then looked at what it returns...
... returns a past-the-end iterator for the new logical end of the range
So the result from std::unique is a sequence which is not necessary the same as the whole vector.
If nothing was removed, the return value would be the end of the vector.
So you want:
vector<int>::iterator it = std::unique(a.begin(), a.end());
bool wasUnique = (it == a.end());
Or for C++11:
auto it = std::unique(a.begin(), a.end());
bool wasUnique = (it == a.end());
Finally for the unique function to work, the vector needs to be sorted, so the complete code would be:
sort(a.begin(), a.end());
auto it = std::unique(a.begin(), a.end());
bool wasUnique = (it == a.end());
You should using set
set<int> s(a.begin(), a.end());
return s.size() != a.size();
If someone is forced to write own algorithm:
bool hasDuplicates(const std::vector<int>& arr) {
for (std::size_t i = 0; i < arr.size(); ++i) {
for (std::size_t j = i + 1; j < arr.size(); ++j) {
if (arr[i] == arr[j])
return true;
}
}
return false;
}
But in real code you should use things that already exist, and in the standard library.
Sort the vector if it's not already sorted, and then use std::unique(), like this:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> v = {3, 1, 3, 4, 5};
sort(v.begin(), v.end());
auto it = std::unique(v.begin(), v.end());
std::cout << ((it == v.end()) ? "Unique\n" : "Duplicate(s)\n");
return 0;
}
Output:
Duplicate(s)
So far all these solutions either modify the container or have O(n²) complexity. You can put a std::map to much better use:
#include <algorithm>
#include <iterator>
#include <map>
template <typename Iterator>
bool has_duplicates( Iterator first, Iterator last )
{
std::map <typename std::iterator_traits <Iterator> ::value_type, std::size_t> histogram;
while (first != last)
if (++histogram[ *first++ ] > 1)
return true;
return false;
}
#include <iostream>
#include <vector>
int main()
{
using std::begin;
using std::end;
int a[] = { 2, 3, 5, 7, 11 };
int b[] = { 2, 3, 5, 5, 7 };
std::vector <int> c( begin(a), end(a) );
std::vector <int> d( begin(b), end(b) );
std::cout << std::boolalpha;
std::cout << "a has duplicates false : " << has_duplicates( begin(a), end(a) ) << "\n";
std::cout << "b has duplicates true : " << has_duplicates( begin(b), end(b) ) << "\n";
std::cout << "c has duplicates false : " << has_duplicates( begin(c), end(c) ) << "\n";
std::cout << "d has duplicates true : " << has_duplicates( begin(d), end(d) ) << "\n";
}
If your vector is small, say < 32 objects, or if copying and sorting the objects is expensive or impossible due to lack of move or copy constructor/assignment then a straight O(n^2) compare everything against everything else algorithm is the way to go.
Here is my solution:
template <typename Iterator>
bool has_duplicates( Iterator first, Iterator end ) {
for (auto i = first; i != end; ++i) {
for (auto j = first; i != j; ++j) {
if (*i == *j) return true;
}
}
return false;
}
template <typename Container>
bool has_duplicates(const Container &v) {
for (const auto & i : v) {
for (const auto & j : v) {
if (&i == &j) break;
if (i == j) return true;
}
}
return false;
}

How to keep track of current and previous iterator on a c++ vector?

I have one vector container and I would like to make a subtraction operation on the values of its content using the current iterator against the previous iterator, any help will be much appreciated
vector<MyClass>::iterator itPrevious = my_vec.begin();
vector<MyClass>::iterator itCurrent = itPrevious;
if (itCurrent != my_vec.end())
{
for (++itCurrent; itCurrent != my_vec.end(); ++itCurrent)
{
// do something with itPrevious and itCurrent
itPrevious = itCurrent;
}
}
std::vector's iterator is a RandomAccessIterator, so you can perform integer arithmetic on it. Thus, you don't need a separate "current" and "previous" pointer, as long as you start your iteration from begin() + 1:
vector<Foo> myVec = ...;
if(myVec.size() > 1) {
for(vector<Foo>::iterator iter = myVec.begin()+1; iter != myVec.end(); iter++) {
Foo current = *iter;
Foo previous = *(iter - 1);
Foo subtraction = current - previous;
...
}
}
Of course, you can't subtract the current and previous element if there are fewer than two elements in your vector. The size check might be redundant if you know your input vector will always have at least two elements, but I included it just to be safe.
Given you asked for a vector, you can use iterator arithmetic:
#include <vector>
#include <iostream>
int main() {
std::vector<int> v{ 1, 2, 3, 4 };
for ( auto i = v.begin(); i != v.end(); ++i ) {
if ( i != v.begin() )
*i = *i - *(i-1);
}
for ( auto i : v )
std::cout << i << std::endl;
}
if(v.size() < 2)
return;
auto curr = v.begin();
auto next = curr;
++next;
do
{
whatever(*next - *curr );
curr = next++;
} while( next != v.end() )
An alternative:
for (auto previous = v.begin(), current = previous + 1, end = v.end();
previous != end && current != end;
++previous, ++current)
{
std::cout << *current << " - " << *previous << " = " << *current - *previous << std::endl;
}
There are namely three more-or-less elegant ways to solve your problem.
Define a new functor
And use it in a for_each iteration
template<class T>
struct substractor {
substractor() : last(nullptr) {}
void operator()(T& item) const
{
if(last != nullptr)
*last -= item;
last = &item;
}
mutable T* last;
};
...
vector<int> v = {3, 2, 1};
for_each(v.begin(), v.end(), substractor<int>());
Define a new algorithm
Some kind of pair in-place transform here
template<typename It, typename Op>
void pair_transform(It begin, It end, Op op){
while(begin != end)
{
It next = std::next(begin);
if(next == end) break;
*begin = op(*begin, *next);
++begin;
}
}
...
vector<int> w = {3, 2, 1};
pair_transform(w.begin(), w.end(), std::minus<int>());
Keep it standard, use transform
IMHO the best one :) Concise, standard, nowhere else to look in order to understand this code.
vector<int> z = {3, 2, 1};
std::transform(z.begin(), z.end() - 1, z.begin() + 1, z.begin(),
std::minus<int>());

Iterating C++ vector from the end to the beginning

Is it possible to iterate a vector from the end to the beginning?
for (vector<my_class>::iterator i = my_vector.end();
i != my_vector.begin(); /* ?! */ ) {
}
Or is that only possible with something like that:
for (int i = my_vector.size() - 1; i >= 0; --i) {
}
One way is:
for (vector<my_class>::reverse_iterator i = my_vector.rbegin();
i != my_vector.rend(); ++i ) {
}
rbegin()/rend() were especially designed for that purpose. (And yes, incrementing a reverse_interator moves it backward.)
Now, in theory, your method (using begin()/end() & --i) would work, std::vector's iterator being bidirectional, but remember, end() isn't the last element — it's one beyond the last element, so you'd have to decrement first, and you are done when you reach begin() — but you still have to do your processing.
vector<my_class>::iterator i = my_vector.end();
while (i != my_vector.begin())
{
--i;
/*do stuff */
}
UPDATE: I was apparently too aggressive in re-writing the for() loop into a while() loop. (The important part is that the --i is at the beginning.)
If you have C++11 you can make use of auto.
for (auto it = my_vector.rbegin(); it != my_vector.rend(); ++it)
{
}
Starting with c++20, you can use a std::ranges::reverse_view and a range-based for-loop:
#include<ranges>
#include<vector>
#include<iostream>
using namespace std::ranges;
std::vector<int> const vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(auto& i : views::reverse(vec)) {
std::cout << i << ",";
}
Or even
for(auto& i : vec | views::reverse)
Unfortunately, at the time of writing (Jan 2020) no major compiler implements the ranges library, but you can resort to Eric Niebler's ranges-v3:
#include <iostream>
#include <vector>
#include "range/v3/all.hpp"
int main() {
using namespace ranges;
std::vector<int> const vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for(auto& i : views::reverse(vec)) {
std::cout << i << ",";
}
return 0;
}
The well-established "pattern" for reverse-iterating through closed-open ranges looks as follows
// Iterate over [begin, end) range in reverse
for (iterator = end; iterator-- != begin; ) {
// Process `*iterator`
}
or, if you prefer,
// Iterate over [begin, end) range in reverse
for (iterator = end; iterator != begin; ) {
--iterator;
// Process `*iterator`
}
This pattern is useful, for example, for reverse-indexing an array using an unsigned index
int array[N];
...
// Iterate over [0, N) range in reverse
for (unsigned i = N; i-- != 0; ) {
array[i]; // <- process it
}
(People unfamiliar with this pattern often insist on using signed integer types for array indexing specifically because they incorrectly believe that unsigned types are somehow "unusable" for reverse indexing)
It can be used for iterating over an array using a "sliding pointer" technique
// Iterate over [array, array + N) range in reverse
for (int *p = array + N; p-- != array; ) {
*p; // <- process it
}
or it can be used for reverse-iteration over a vector using an ordinary (not reverse) iterator
for (vector<my_class>::iterator i = my_vector.end(); i-- != my_vector.begin(); ) {
*i; // <- process it
}
User rend() / rbegin() iterators:
for (vector<myclass>::reverse_iterator it = myvector.rbegin(); it != myvector.rend(); it++)
template<class It>
std::reverse_iterator<It> reversed( It it ) {
return std::reverse_iterator<It>(std::forward<It>(it));
}
Then:
for( auto rit = reversed(data.end()); rit != reversed(data.begin()); ++rit ) {
std::cout << *rit;
Alternatively in C++14 just do:
for( auto rit = std::rbegin(data); rit != std::rend(data); ++rit ) {
std::cout << *rit;
In C++03/11 most standard containers have a .rbegin() and .rend() method as well.
Finally, you can write the range adapter backwards as follows:
namespace adl_aux {
using std::begin; using std::end;
template<class C>
decltype( begin( std::declval<C>() ) ) adl_begin( C&& c ) {
return begin(std::forward<C>(c));
}
template<class C>
decltype( end( std::declval<C>() ) ) adl_end( C&& c ) {
return end(std::forward<C>(c));
}
}
template<class It>
struct simple_range {
It b_, e_;
simple_range():b_(),e_(){}
It begin() const { return b_; }
It end() const { return e_; }
simple_range( It b, It e ):b_(b), e_(e) {}
template<class OtherRange>
simple_range( OtherRange&& o ):
simple_range(adl_aux::adl_begin(o), adl_aux::adl_end(o))
{}
// explicit defaults:
simple_range( simple_range const& o ) = default;
simple_range( simple_range && o ) = default;
simple_range& operator=( simple_range const& o ) = default;
simple_range& operator=( simple_range && o ) = default;
};
template<class C>
simple_range< decltype( reversed( adl_aux::adl_begin( std::declval<C&>() ) ) ) >
backwards( C&& c ) {
return { reversed( adl_aux::adl_end(c) ), reversed( adl_aux::adl_begin(c) ) };
}
and now you can do this:
for (auto&& x : backwards(ctnr))
std::cout << x;
which I think is quite pretty.
Use reverse iterators and loop from rbegin() to rend()
I like the backwards iterator at the end of Yakk - Adam Nevraumont's answer, but it seemed complicated for what I needed, so I wrote this:
template <class T>
class backwards {
T& _obj;
public:
backwards(T &obj) : _obj(obj) {}
auto begin() {return _obj.rbegin();}
auto end() {return _obj.rend();}
};
I'm able to take a normal iterator like this:
for (auto &elem : vec) {
// ... my useful code
}
and change it to this to iterate in reverse:
for (auto &elem : backwards(vec)) {
// ... my useful code
}
If you can use The Boost Library, there is the Boost.Range that provides the reverse range adapter by including:
#include <boost/range/adaptor/reversed.hpp>
Then, in combination with a C++11's range-for loop, you can just write the following:
for (auto& elem: boost::adaptors::reverse(my_vector)) {
// ...
}
Since this code is briefer than the one using the iterator pair, it may be more readable and less prone to errors as there are fewer details to pay attention to.
Here's a super simple implementation that allows use of the for each construct and relies only on C++14 std library:
namespace Details {
// simple storage of a begin and end iterator
template<class T>
struct iterator_range
{
T beginning, ending;
iterator_range(T beginning, T ending) : beginning(beginning), ending(ending) {}
T begin() const { return beginning; }
T end() const { return ending; }
};
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// usage:
// for (auto e : backwards(collection))
template<class T>
auto backwards(T & collection)
{
using namespace std;
return Details::iterator_range(rbegin(collection), rend(collection));
}
This works with things that supply an rbegin() and rend(), as well as with static arrays.
std::vector<int> collection{ 5, 9, 15, 22 };
for (auto e : backwards(collection))
;
long values[] = { 3, 6, 9, 12 };
for (auto e : backwards(values))
;
can try this one (only for --i):
std:vector<int> vec = {1, 2, 3};
size_t i{ vec.size() - 1 };
while (i < size_t(-1))
{
auto& el = vec[i];
--i;
}
use this code
//print the vector element in reverse order by normal iterator.
cout <<"print the vector element in reverse order by normal iterator." <<endl;
vector<string>::iterator iter=vec.end();
--iter;
while (iter != vec.begin())
{
cout << *iter << " ";
--iter;
}
As I don't want to introduce alien-like new C++ syntax, and I simply want to build up on existing primitives, the below snippets seems to work:
#include <vector>
#include <iostream>
int main (int argc,char *argv[])
{
std::vector<int> arr{1,2,3,4,5};
std::vector<int>::iterator it;
// iterate forward
for (it = arr.begin(); it != arr.end(); it++) {
std::cout << *it << " ";
}
std::cout << "\n************\n";
if (arr.size() > 0) {
// iterate backward, simple Joe version
it = arr.end() - 1;
while (it != arr.begin()) {
std::cout << *it << " ";
it--;
}
std::cout << *it << " ";
}
// iterate backwards, the C++ way
std::vector<int>::reverse_iterator rit;
for (rit = arr.rbegin(); rit != arr.rend(); rit++) {
std::cout << *rit << " ";
}
return 0;
}