Why is this iterator arithmetic not working? - c++

I am learning C++ for fun. I am trying to understand iterator arithmetic and have written a simple program that sums the first element in a vector with the last element. Next the second and second-to-last elements are summed. The process continues until all elements have been summed in this manner.
The issue seems to be with the *(a.end() - 1 - it) portion of my code. If I remove the - it, then I get the result I would expect. Adding the - it results in an error saying that
there were build errors. Would you like to continue to run the last successful build?
The errors I receive from Visual Studio are as follows;
E0075 Operand of * must be a pointer
C2100 illegal indirection
I have already approached this problem in a different way and was able to accomplish my goal. My question is why is this code an error, and could it be modified slightly to execute properly?
I appreciate any advice.
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
int main()
{
vector<int> a{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto it = a.begin(); it != a.begin() + (a.end() - a.begin()) / 2; ++it)
cout << (*it) + *(a.end() - 1 - it) << endl;
return 0;
} // END MAIN
Error message
Error list

Subtracting 2 iterators with a.end() - 1 - it gives you the distance between them. You can't dereference a distance with * and so you get a compiler error.
This distance from a.begin() to the element you want to get at is needed in the expression. You can adjust the expression slightly by just adding a.begin() to that distance:
cout << (*it) + *(a.end() - 1 - it + a.begin()) << endl;
// ^^^^^^^^^^^
Here's a demo.
From C++20, instead of dealing with iterators and manipulating them, you can deal with ranges directly, which can be easier to read once you get used to it:
// just for convenience
namespace sv = std::views;
namespace sr = std::ranges;
// size of half the range
auto half = a.size() / 2;
sr::transform(a | sv::take(half), // first half
a | sv::reverse | sv::take(half), // second half reversed
std::ostream_iterator<int>(std::cout, "\n"), // print out
std::plus{}); // the sum
Here's a demo.

You should change code like this:
auto fix = it - a.begin();
cout << (*it) + *(a.end() - 1 - fix) << endl;
you can't manipulate on iterators like integers, you just can simply add or sub integers or use starting point from begin() - as end() isn't a real pointer for some value in vector.

Related

What is the difference between range-v3 views::drop and views::drop_exactly?

Can someone explain the difference between range-v3's view adaptors drop and drop_exactly?
One difference I've observed is that if the number of elements in the range that is piped to these views is less than the argument to the view adaptors, drop seems to do the right thing, while drop_exactly seems to invoke UB.
When the argument is less than the number of elements in the range that is piped to these views, they both seem to work the same:
#include <iostream>
#include <vector>
#include <range/v3/all.hpp>
namespace rv = ranges::views;
int main()
{
std::vector<int> v { 1, 2, 3, 4, 5};
for (int i : v | rv::drop(3))
std::cout << i; // prints 45
for (int i : v | rv::drop(7))
std::cout << i; // prints nothing
for (int i : v | rv::drop_exactly(3))
std::cout << i; // prints 45
for (int i : v | rv::drop_exactly(7))
std::cout << i; // prints garbage and crashes
}
Here's the code.
From the documentation for drop_exactly:
Given a source range and an integral count, return a range consisting
of all but the first count elements from the source range. The
source range must have at least that many elements.
While the documentation for drop states:
Given a source range and an integral count, return a range consisting
of all but the first count elements from the source range, or an
empty range if it has fewer elements.
emphasis added
I'm guessing that drop_exactly avoids bounds checks and therefore has the potential to be slightly more performant at the cost of maybe running past the end of the piped-in container, while drop apparently performs bounds checks to make sure you don't.
This is consistent with what you see. If you print stuff from begin()+7 up to begin()+5 (aka end()) of a std::vector, and the abort condition is implemented with != instead of <, then you will continue to print the junk data that sits in the space allocated by the vector until at some point you run over the allocated chunk and the operating system steps in and segfaults your binary.
So, if you know the container to have as many entries as you wish to drop use the faster drop_exactly, otherwise use drop.

lower_bound() in C++

From reading from the Internet, I understand that The lower_bound() method in C++ is used to return an iterator pointing to the first element in the range [first, last) which has a value not less than value. This means that the function returns the index of the next smallest number just greater than that number.
So, for the given code below I understood that the output is 3. But, as there is repetition of 6. How can I get the index of last 6 using lower_bound(). I can implement my own binary_search() for that, but I want to know how to do it by lower_bound().
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main ()
{
int array[] = {5,6,7,7,6,5,5,6};
vector<int> v(array,array+8); // 5 6 7 7 6 5 5 6
sort (v.begin(), v.end()); // 5 5 5 6 6 6 7 7
vector<int>::iterator lower,upper;
lower = lower_bound (v.begin(), v.end(), 6);
upper = upper_bound (v.begin(), v.end(), 6);
cout << "lower_bound for 6 at position " << (lower- v.begin()) << '\n';
return 0;
}
Use pair of lower_bound and upper_bound. Or one equal_range -- that would be more optimal.
Both upper_bound and high part of equal_range would be past the last "6". The same as end is not last, it is past the last.
You can use reverse iterators into the vector, but then to fulfill the ordering requirement for std::lower_bound you need to inverse the comparison, so you need to use std::greater instead of the default std::less. This however also means that now you are not really looking for a lower bound, but for an upper bound with respect to that comparison function, so:
auto upper = std::upper_bound(v.rbegin(), v.rend(), 6, std::greater{});
If the array is sorted, iterating between lower_bound and upper_bound you get all elements which equal your pivot point:
lower = lower_bound(v.begin(), v.end(), 6);
upper = upper_bound(v.begin(), v.end(), 6);
for (auto it = lower; it != upper; it++) {
assert(6 == *it);
}
The question you are asking, i.e. what is the index of the last 6, doesn't have a corresponding function in the standard library because is ill-defined in the case when the range doesn't contain any 6. In all other cases since you have a random access container you can get an iterator to the last 6 by removing one from upper_bound (upper - 1 in your code), in the same way you get the last index of an array by removing 1 from length.
However I suggest you avoid relying on the position of the last element equal when you design your algorithm. Also note that if you need both lower and upper bound you can get both at the same time with equal_range, which may even perform better because it may be optimised to only traverse the data structure once:
std::tie(lower,upper) = equal_range(v.begin(), v.end(), 6);
for (auto it = lower; it != upper; it++) {
assert(6 == *it);
}
You can use lower_bound again, updating the begin and the value:
auto lower = std::lower_bound (v.cbegin(), v.cend(), 6);
auto upper = std::lower_bound (lower, v.cend(), 6 + 1);
std::cout << "Number of values found: " << std::distance(lower, upper) << '\n';

C++ forward iterator arithmetic

Below is a simple program to print the position within a vector of a small range of ints.
int mynumbers [] = { 3, 9, 0, 2, 1, 4, 5 };
vector<int> v (mynumbers, mynumbers + 7);
int m1[] = {9, 0, 2 };
vector<int>::iterator it = find_end (v.begin(), v.end(), m1, m1+3);
if (it != v.end())
cout << "Found at position: " << it-v.begin() << endl;//LINE I
The program as expected prints
Found at position: 1
the find_end function returns a forward iterator.
Logically it makes no sense for me to do so but when I change 'LINE I' to
cout << "Found at position: " << it+v.begin() << endl;//LINE I
I get a compile error.
I know I should be using 'distance' however I am just trying to familiarise myself with the limitations of the various iterator types
Thanks
it is an iterator, it represents a location where an object is.
You say "logically it makes no sense for me to do so..." about it+v.begin(), which is right, because you're adding two locations. What do you get when you add the location of Californa to the location of New York? The question literally makes no sense.
However, you can take the distance between two locations: it-v.begin(). Not sure exactly what you're asking, but I hopefully covered it.
The simple answer is that there is an operation defined for b - a, where b and a are of the same iterator types, but there is no operation defined for b + a.
Sources:
Non-normative: cppreference, RandomAccessIterator
Normative: N4140, [random.access.iterators] Table 111
You're on the right track.
But I think the distance that you mention in your question is your actual solution: http://www.cplusplus.com/reference/iterator/distance/
This is your situation:
begin() --> 3
it --> 9
0
2
1
4
5
distance(v.begin(), it) will tell you how far those two pointers are apart. (In this case 1).
Now keep in mind under the hood distance will just do the same subtraction that you do in this case.
How you should think about it is like this, v.begin() is an address and so is it.
v.begin() is 0x0100
it is 0x0104
when you subtract them you're going to get (0x0104 - 0x0100) / sizeof(int) so you'll get 1.

lower_bound == upper_bound

What does lower_bound mean. If I had to guess I would answer that this function returns the iterator at the last element that is less than the value asked for. But I see that lower_bound is almost the same as upper_bound. The only difference is strict inequality in the case of upper_bound. Is there a true lower bound selection function in stl that agrees with the normal definition of lower bound.
EDIT: It was too many negations in the docs which made me confused. The problem was that I got the same iterator. I solved it by subtracting 1 from lower_bound return value. I use it for interpolation:
float operator()(double f)
{
SpectrumPoint* l=std::lower_bound(beginGet(),endGet(),(SpectrumPoint){float(f),0.0f}
,SpectrumPoint::CompareFreqLessThan);
if(l>beginGet())
{--l;}
SpectrumPoint* u=std::lower_bound(beginGet(),endGet(),(SpectrumPoint){float(f),0.0f}
,SpectrumPoint::CompareFreqLessThan);
if(u==endGet())
{u=beginGet();}
if(l==u)
{
if(u==endGet())
{return u->amp;}
return l->amp;
}
double f_min=l->freq;
double A_min=l->amp;
double f_max=u->freq;
double A_max=u->amp;
double delta_f=f_max-f_min;
double delta_A=A_max-A_min;
return A_min + delta_A*(f-f_min)/delta_f;
}
I am sorry for this confusion :-(
Lower bound: first element that is greater-or-equal.
Upper bound: first element that is strictly greater.
Example:
+- lb(2) == ub(2) +- lb(6) +- lb(8)
| == begin() | == ub(6) | +- ub(8) == end()
V V V V
+---+---+---+---+---+---+---+---+---+---+---+
| 3 | 4 | 4 | 4 | 4 | 5 | 7 | 7 | 7 | 7 | 8 |
+---+---+---+---+---+---+---+---+---+---+---+
^ ^ ^
| | |
+- lb(4) +- ub(4) +- lb(9) == ub(9) == end()
|- eq-range(4) -|
As you can see, the half-open equal-range for n is [lb(n), ub(n)).
Note that both bounds give you meaningful insertion locations for an element of the desired value so that the ordering is maintained, but lower_bound has the distinguishing feature that if the element already exists, then you get an iterator which actually points to that element. Thus you can use lower_bound on an ordered range to implement your own unique-membership or multiple-membership container.
void insert(Container & c, T const & t)
{
auto it = std::lower_bound(c.begin(), c.end(), t);
// if unique container:
if (it != c.end() && *it == t) { /* error, element exists! */ return; }
c.insert(it, t);
}
It returns the iterator one past the last element that is less than the value asked for. This is useful as an insertion position (and that's why the function returns that iterator). It's also useful that the half-open range first, lower_bound(first, last, value) specifies all values less than value.
upper_bound returns the iterator one past the last element [less than or equal to / not greater than] the value asked for. Or strictly: the last element which the value is not less than, since both algorithms deal exclusively in less-than comparators.
If you want the iterator before the iterator returned by lower_bound, you can subtract 1 (for a random access iterator), decrement (for a bidirectional iterator), or do a linear search instead of using lower_bound (for a forward iterator that is none of those).
Beware the edge case that there is no element less than the value asked for, in which case you can't have what you want, because it doesn't exist. lower_bound of course returns the beginning of the range in that case, so doesn't need a special-case return value.
Since this has been reopened, I'll try to make my comment an answer.
The name lower_bound is mathematically incorrect. A better name might be least_upper_bound, but that would probably confuse most non-mathematically minded folk. (And then what do you call upper_bound? almost_least_upper_bound? Yech!)
My advice: Get over the fact that the names lower_bound and upper_bound are technically incorrect. The two functions as defined are quite useful. Think of those functions as a useful abuse of notation.
To make a mathematically correct lower_bound function that conforms with the C++ concept of an iterator, the function would have to return a reverse iterator rather than a forward iterator. Returning a reverse iterator is not nearly as useful as the approach taken by the perhaps misnamed lower_bound and upper_bound, and the concept of returning a reverse iterator runs afoul of the fact that not all containers are reversible.
Why a reverse iterator? Just as there is no guarantee that an upper bound exists in the container, there similarly is no guarantee that a lower bound will exist. The existing lower_bound and upper_bound return end() to indicate that the searched-for value is off-scale high. A true lower bound would need to return rend() to indicate that the searched-for value is off-scale low.
There is a way to implement a true lower bound in the form of a forward iterator, but it comes at the price of abusing the meaning of end() to mean "there is no lower bound". The problem with this abuse of notation is that some user of the function might do something equivalent to true_lower_bound(off_scale_low_search_value)-1 and voila! one has a pointer to the largest element in the set.
That said, here's how to do it. Have the true lower bound function return end() if the container is empty or if the searched-for value is smaller than the first value in the container. Otherwise return upper_bound()-1.
lower_bound, upper_bound and equal_range are functions which perform binary search in a sorted sequence. The need for three functions comes from the fact that elements may be repeated in the sequence:
1, 2, 3, 4, 4, 4, 5, 6, 7
In this case, when searching for the value 4, lower_bound will return an iterator pointing to the first of the three elements with value 4, upper_bound will return an iterator pointing to the element with value 5, and equal_range will return a pair containing these two iterators.
Following David Hammen's answer, I attempted to explain why we often don't feel the names of lower_bound/upper_bound to be correct, or at least intuitive.
It's because we are looking for an element immediately lower than the query.
I made a drawing and a use case:
Code:
template< typename T, typename U >
auto infimum(std::map<T,U> const& ctr, T query)
{
auto it = ctr.upper_bound(query);
return it == ctr.begin() ? ctr.cend() : --it;
}
template< typename T, typename U >
bool is_in_interval(std::map<T,U> const& ctr, T query)
{
auto inf = infimum(ctr, query);
return inf == ctr.end() ? false : query <= inf->second;
}
https://ideone.com/jM8pt3
Basically to get the behavior of the "grey arrows", we need upper_bound - 1 which is why it's weird.
Let me rephrase that slightly: from the name lower_bound we instinctively expect returns-first-immediately-inferior-element (like the grey arrows). But we get returns-first-immediately-superior-element for lower_bound; and first-immediately-strictly-superior-element for upper_bound. That's what is surprising.
It's surprising in the hypothesis that you work with a sparse sequence like my thought experiment in the picture above. But it makes wonderful sense when you think of it in terms of «bounds of an equal_range» in a dense sequence, populated with plateaus, like Kerrek SB beautifully pictured.
Test code:
#include <map>
#include <cassert>
#include <iostream>
// .. paste infimum and is_in_interval here
int main()
{
using std::cout;
using Map = std::map<int,int>;
Map intervals{{2,5}, {8,9}};
auto red = infimum(intervals, 4);
assert(red->first == 2);
cout << "red->first " << red->first << "\n";
auto green = infimum(intervals, 6);
assert(green->first == 2);
cout << "green->first " << green->first << "\n";
auto pink = infimum(intervals, 8);
assert(pink->first == 8);
cout << "pink->first " << pink->first << "\n";
auto yellow = infimum(intervals, 1);
assert(yellow == intervals.cend());
auto larger_than_all = infimum(intervals, 15);
assert(larger_than_all->first == 8);
bool red_is = is_in_interval(intervals, 4);
cout << "red is in " << red_is << "\n";
bool green_is = is_in_interval(intervals, 6);
cout << "green is in " << green_is << "\n";
bool pink_is = is_in_interval(intervals, 8);
cout << "pink is in " << pink_is << "\n";
bool yellow_is = is_in_interval(intervals, 1);
cout << "yellow is in " << yellow_is << "\n";
}
results in
red->first 2
green->first 2
pink->first 8
red is in 1
green is in 0
pink is in 1
yellow is in 0
seems ok.
So of course the utility functions are not very good, they should be designed with a range API, so we can work with any collection or sub-range, or reverse iterators, or filtered views and whatnot. We can get that when we have C++20. In the meantime, I just made a simple educative map-taking API.
play with it:
https://ideone.com/jM8pt3
Another usage of lower_bound and upper_bound is to find a range of equal elements in a container, e.g.
std::vector<int> data = { 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6 };
auto lower = std::lower_bound(data.begin(), data.end(), 4);
auto upper = std::upper_bound(lower, data.end(), 4);
std::copy(lower, upper, std::ostream_iterator<int>(std::cout, " "));
Auch!
Did you change the original code or is the copy-paste error in there since day one?
float operator()(double f)
{
SpectrumPoint* l=std::lower_bound//...
...
SpectrumPoint* u=std::lower_bound//...
...
}
In the code I read today you are assigning lower_bound to both 'l' and 'u'.

C++ Arrays manipulations (python-like operations)

I'm trying to figure out the best C++ library/package for array manipulations in a manner of python. Basically I need a simplicity like this:
values = numpy.array(inp.data)
idx1 = numpy.where(values > -2.14)
idx2 = numpy.where(values < 2.0)
res1 = (values[idx1] - diff1)/1000
res2 = (values[idx2] - diff2)*1000
In python it's just 5 lines, but the simplest way in C++ i can think of is quite a number of nested loops. Pls advise..
Basically my question is concerning the array/vector operations like array multiplications, operations on indexs, etc.. In the example above, res1 is an array, containing a set of elements filtered out of values array and some arithmetics applied afterward (subtraction, multiplication for all selected elements). In this python example I'm not copying elements of values array as it could be big enough in terms of memory, i'm keeping only the indexes and want to be able to run arithmetic operations on a selected set of elements of the original array.
You should not be using arrays at all. Please sit down and learn about the std::vector class and about iterators and Standard Library algorithms. I strongly suggest reading the book The C++ Standard Library.
You can achieve something similar in C++ but you shouldn't use plain C arrays for it.
The easiest way I can see this work would be using a std::set of floats (your code looks like it assumes that the data is sorted in ascending order). You could also use a std::vector of float but you'll have to sort that yourself, probably by using std::sort.
In that case, your example code could look like this - the set assumes the values are unique, if they aren't, you could use a std::multiset instead;
std::set<float> values(inp.data.begin(), inp.data.end());
std::set<float>::iterator idx1 = values.lower_bound(-2.14);
std::set<float>::iterator idx2 = values.upper_bound(2.0);
float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;
Please note that the above code sample is not a 100% conversion of your original code - lower_boundgives you the first element that's equal or larger than -2.14. I also didn't put any checking code in for failures - if lower_bound or upper_bound can't find matching elements, they would return values.end(), for example.
Using vector, the example would look very similar, just one line more to pre-sort the vector:
std::vector<float> values(inp.data.begin(), inp.data.end());
std::sort(values.begin(), values.end();
std::vector<float>::iterator idx1 = std::lower_bound(values.begin(), values.end(), -2.14);
std::vector<float>::iterator idx2 = std::upper_bound(values.begin(), values.end(), 2.0);
float res1 = (*idx1 - diff1) / 1000.0;
float res2 = (*idx2 - diff2) / 1000.0;
I suggest you to check the algorithm header.
Also don't work with arrays, you have std::vector or boost(soon to be std)::array.
wikipedia article
Reference for all algorithms
If I'm not mistaken, numpy is written mostly in C (with a Python wrapper), so you could be able to use it directly from C++ without much effort.
If you combine std::vector and boost::lambda, you can come really close to your example:
#include <algorithm>
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
using boost::lambda::_1;
int main() {
float ary[10] = { -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 };
std::vector<float> v(&ary[0], &ary[10]);
std::vector<float>::iterator iter1, iter2;
iter1 = std::find_if(v.begin(), v.end(), (_1 > -2.14));
iter2 = std::find_if(v.begin(), v.end(), (_1 < 2.0));
// output:
// iter1 = -2.000
// iter2 = 1.000
std::cout
<< "iter1 = " << *iter1 << "\n"
<< "iter2 = " << *iter2 << "\n"
<< std::endl;
return 0;
}