How do iterators map/know their current position or element - c++

Consider the following code example :
#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>
int main()
{
std::vector<int> v(10, 2);
std::partial_sum(v.cbegin(), v.cend(), v.begin());
std::cout << "Among the numbers: ";
std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; })) {
std::cout << "All numbers are even\n";
}
if (std::none_of(v.cbegin(), v.cend(), std::bind(std::modulus<int>(),
std::placeholders::_1, 2))) {
std::cout << "None of them are odd\n";
}
struct DivisibleBy
{
const int d;
DivisibleBy(int n) : d(n) {}
bool operator()(int n) const { return n % d == 0; }
};
if (std::any_of(v.cbegin(), v.cend(), DivisibleBy(7))) {
std::cout << "At least one number is divisible by 7\n";
}
}
If we look at this part of the code :
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; })) {
std::cout << "All numbers are even\n";
}
which is fairly easy to understand. It iterates over those vector elements , and finds out i%2==0 , whether they are completely divisible by 2 or not , hence finds out they're even or not.
Its for loop counterpart could be something like this :
for(int i = 0; i<v.size();++i){
if(v[i] % 2 == 0) areEven = true; //just for readablity
else areEven = false;
}
In this for loop example , it is quiet clear that the current element we're processing is i since we're actually accessing v[i]. But how come in iterator version of same code , it maps i or knows what its current element is that we're accessing?
How does [](int i){ return i % 2 == 0; }) ensures/knows that i is the current element which iterator is pointing to.
I'm not able to makeout that without use of any v.currently_i_am_at_this_posiition() , how is iterating done. I know what iterators are but I'm having a hard time grasping them. Thanks :)

Iterators are modeled after pointers, and that's it really. How they work internally is of no interest, but a possible implementation is to actually have a pointer inside which points to the current element.

Iterating is done by using an iterator object
An iterator is any object that, pointing to some element in a range of
elements (such as an array or a container), has the ability to iterate
through the elements of that range using a set of operators (with at
least the increment (++) and dereference (*) operators).
The most obvious form of iterator is a pointer: A pointer can point to
elements in an array, and can iterate through them using the increment
operator (++).
and advancing it through the set of elements. The std::all_of function in your code is roughly equivalent to the following code
template< class InputIt, class UnaryPredicate >
bool c_all_of(InputIt first, InputIt last, UnaryPredicate p)
{
for (; first != last; ++first) {
if (!p(*first)) {
return false; // Found an odd element!
}
}
return true; // All elements are even
}
An iterator, when incremented, keeps track of the currently pointed element, and when dereferenced it returns the value of the currently pointed element.
For teaching's and clarity's sake, you might also think of the operation as follows (don't try this at home)
bool c_all_of(int* firstElement, size_t numberOfElements, std::function<bool(int)> evenTest)
{
for (size_t i = 0; i < numberOfElements; ++i)
if (!evenTest(*(firstElement + i)))
return false;
return true;
}
Notice that iterators are a powerful abstraction since they allow consistent elements access in different containers (e.g. std::map).

Related

Is it possible to remove elements from a vector of shared_ptr?

Say I have
vector<shared_ptr<string>> enemy;
how do I remove elements from the enemy vector?
Thanks for your help in advance
**Edit (code in context)
void RemoveEnemy( vector<shared_ptr<Enemy>> & chart, string id )
{
int i = 0;
bool found = FALSE;
for(auto it = chart.begin(); it != chart.end(); i++)
{
if(id == chart[i]->GetEnemyID() )
{
found = TRUE;
chart.erase(it);
}
}
the code above segfaults me
You remove elements the same way you remove any elements from any std::vector - via the std::vector::erase() method, for instance. All you need for that is an iterator to the desired element to remove.
In your case, since you are storing std::shared_ptr<std::string> objects rather than storing actual std::string objects, you may need to use something like std::find_if() to find the vector element containing the desired string value, eg:
void removeEnemy(string name)
{
auto iter = std::find_if(enemy.begin(), enemy.end(),
[&](auto &s){ return (*s == name); }
);
if (iter != enemy.end())
enemy.erase(iter);
}
UPDATE: in the new code you have added, you are incorrectly mixing indexes and iterators together. You are creating an infinite loop if the vector is not empty, as you never increment the it iterator that controls your loop, you are incrementing your index i variable instead (see what happens when you don't give your variables unique and meaningful names?). So you end up going out of bounds of the vector into surrounding memory. That is why you get the segfault error.
Even though you are (trying to) use an iterator to loop through the vector, you are using indexes to access the elements, instead of dereferencing the iterator to access the elements. You don't need to use indexes at all in this situation, the iterator alone will suffice.
Try this instead:
void RemoveEnemy( vector<shared_ptr<Enemy>> & chart, string id )
{
for(auto it = chart.begin(); it != chart.end(); ++it)
{
if (id == it->GetEnemyID() )
{
chart.erase(it);
return;
}
}
Or, using the kind of code I suggested earlier:
void RemoveEnemy( vector<shared_ptr<Enemy>> & chart, string id )
{
auto iter = std::find_if(chart.begin(), chart.end(),
[&](auto &enemy){ return (enemy->GetEnemyID() == id); }
);
if (iter != chart.end())
chart.erase(iter);
}
The problem with your code is that erase() invalidates the iterator. You must use it = chart.erase(it).
I like mine which will remove aliens at high speed and without any care for the ordering of the other items. Removal with prejudice!
Note: remove_if is most often used with erase and it will preserve the order of the remaining elements. However, partition does not care about the ordering of elements and is much faster.
partition-test.cpp:
make partition-test && echo 1 alien 9 alien 2 8 alien 4 7 alien 5 3 | ./partition-test
#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <vector>
using namespace std;
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &container) {
bool comma = false;
for (const auto &x : container) {
if (comma)
os << ", ";
os << *x;
comma = true;
}
return os;
}
int main() {
vector<shared_ptr<string>> iv;
auto x = make_shared<string>();
while (cin >> *x) {
iv.push_back(x);
x = make_shared<string>();
}
cout << iv << '\n';
iv.erase(partition(begin(iv), end(iv),
[](const auto &x) { return *x != "alien"s; }),
end(iv));
cout << iv << '\n';
return 0;
}

Convenient way to return filtered collection

Problem
Suppose I have two iterators begin and end of type Iterator and some predicate predicate (stored in obj). I want to implement method some_collection() o that I can write
for(auto element: obj.get_collection()) {
do_smth()
}
so that it's work only on elements which satisfy predicate (i.e eqiuvalent to smth like this)
for (auto element: range(begin, end)) {
if (predicate(element)) {
do_smth();
}
}
My solution
Approximate implementation I have in mind is the following (pseudocode):
struct Wrapper {
op++() {
do {
++value;
while (!predicate(*value));
}
op*() {
return *value;
}
op !=(Iterator other) {
return value != other.value;
}
Iterator value;
}
Where begin() of returned object will be like
value = begin;
while (!predicate(*value)) ++value;
return Wrapper(value)
and end() is just Wrapper(end)
Caveats
What I don't like in this implementation:
Wordiness: I just need to filter, and have to write ton of code
Initialisation is kind of ugly - have to increment right there
If I won't iterate over all objects (will break or just don't use any values) I'll iterate extra (to the next unused element)
I could iterate before each dereference (to fix 2nd and 3rd points) but it will make != end check harder (either I need to decrement end in advance or use increment in check itself which means passing input range two times during the cycle)
Requirements
I don't have specific language version requirements and even interested in implementations using not yet approved. But C++11 would be the greatest
I don't have specific requirements for iterator category supported. I believe Mine will work with ForwardIterators.
I'm interested in both understandability of the code and its efficiency.
Any solution that is closer to silver bullet? :)
You could use a BOOST filter_iterator. Here is the example from the linked page:
struct is_positive_number {
bool operator()(int x) { return 0 < x; }
};
int main()
{
int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
const int N = sizeof(numbers_)/sizeof(int);
typedef int* base_iterator;
base_iterator numbers(numbers_);
// Example using filter_iterator
typedef boost::filter_iterator<is_positive_number, base_iterator>
FilterIter;
is_positive_number predicate;
FilterIter filter_iter_first(predicate, numbers, numbers + N);
FilterIter filter_iter_last(predicate, numbers + N, numbers + N);
std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// Example using make_filter_iterator()
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// Another example using make_filter_iterator()
std::copy(
boost::make_filter_iterator(
std::bind2nd(std::greater<int>(), -2)
, numbers, numbers + N)
, boost::make_filter_iterator(
std::bind2nd(std::greater<int>(), -2)
, numbers + N, numbers + N)
, std::ostream_iterator<int>(std::cout, " ")
);
std::cout << std::endl;
return boost::exit_success;
}

Output over unique elements of `std::multiset` and their frequency using std:: algorithm in C++ (no loops)

I have the following multiset in C++:
template<class T>
class CompareWords {
public:
bool operator()(T s1, T s2)
{
if (s1.length() == s2.length())
{
return ( s1 < s2 );
}
else return ( s1.length() < s2.length() );
}
};
typedef multiset<string, CompareWords<string>> mySet;
typedef std::multiset<string,CompareWords<string>>::iterator mySetItr;
mySet mWords;
I want to print each unique element of type std::string in the set once and next to the element I want to print how many time it appears in the list (frequency), as you can see the functor "CompareWord" keeps the set sorted.
A solution is proposed here, but its not what I need, because I am looking for a solution without using (while,for,do while).
I know that I can use this:
//gives a pointer to the first and last range or repeated element "word"
auto p = mWords.equal_range(word);
// compute the distance between the iterators that bound the range AKA frequency
int count = static_cast<int>(std::distance(p.first, p.second));
but I can't quite come up with a solution without loops?
Unlike the other solutions, this iterates over the list exactly once. This is important, as iterating over a structure like std::multimap is reasonably high overhead (the nodes are distinct allocations).
There are no explicit loops, but the tail-end recursion will be optimized down to a loop, and I call an algorithm that will run a loop.
template<class Iterator, class Clumps, class Compare>
void produce_clumps( Iterator begin, Iterator end, Clumps&& clumps, Compare&& compare) {
if (begin==end) return; // do nothing for nothing
typedef decltype(*begin) value_type_ref;
// We know runs are at least 1 long, so don't bother comparing the first time.
// Generally, advancing will have a cost similar to comparing. If comparing is much
// more expensive than advancing, then this is sub optimal:
std::size_t count = 1;
Iterator run_end = std::find_if(
std::next(begin), end,
[&]( value_type_ref v ){
if (!compare(*begin, v)) {
++count;
return false;
}
return true;
}
);
// call our clumps callback:
clumps( begin, run_end, count );
// tail end recurse:
return produce_clumps( std::move(run_end), std::move(end), std::forward<Clumps>(clumps), std::forward<Compare>(compare) );
}
The above is a relatively generic algorithm. Here is its use:
int main() {
typedef std::multiset<std::string> mySet;
typedef std::multiset<std::string>::iterator mySetItr;
mySet mWords { "A", "A", "B" };
produce_clumps( mWords.begin(), mWords.end(),
[]( mySetItr run_start, mySetItr /* run_end -- unused */, std::size_t count )
{
std::cout << "Word [" << *run_start << "] occurs " << count << " times\n";
},
CompareWords<std::string>{}
);
}
live example
The iterators must refer to a sorted sequence (with regards to the Comparator), then the clumps will be passed to the 3rd argument together with their length.
Every element in the multiset will be visited exactly once with the above algorithm (as a right-hand side argument to your comparison function). Every start of a clump will be visited (length of clump) additional times as a left-hand side argument (including clumps of length 1). There will be exactly N iterator increments performed, and no more than N+C+1 iterator comparisons (N=number of elements, C=number of clumps).
#include <iostream>
#include <algorithm>
#include <set>
#include <iterator>
#include <string>
int main()
{
typedef std::multiset<std::string> mySet;
typedef std::multiset<std::string>::iterator mySetItr;
mySet mWords;
mWords.insert("A");
mWords.insert("A");
mWords.insert("B");
mySetItr it = std::begin(mWords), itend = std::end(mWords);
std::for_each<mySetItr&>(it, itend, [&mWords, &it] (const std::string& word)
{
auto p = mWords.equal_range(word);
int count = static_cast<int>(std::distance(p.first, p.second));
std::cout << word << " " << count << std::endl;
std::advance(it, count - 1);
});
}
Outputs:
A 2
B 1
Live demo link.
Following does the job without explicit loop using recursion:
void print_rec(const mySet& set, mySetItr it)
{
if (it == set.end()) {
return;
}
const auto& word = *it;
auto next = std::find_if(it, set.end(),
[&word](const std::string& s) {
return s != word;
});
std::cout << word << " appears " << std::distance(it, next) << std::endl;
print_rec(set, next);
}
void print(const mySet& set)
{
print_rec(set, set.begin());
}
Demo

Keeping track of removed elements using std::remove_if

I want to remove some elements from a vector and am using remove_if algorithm to do this. But I want to keep track of the removed elements so that I can perform some operation on them later. I tried this with the following code:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
struct IsEven
{
bool operator()(int n)
{
if(n % 2 == 0)
{
evens.push_back(n);
return true;
}
return false;
}
vector<int> evens;
};
int main(int argc, char **argv)
{
vector<int> v;
for(int i = 0; i < 10; ++i)
{
v.push_back(i);
}
IsEven f;
vector<int>::iterator newEnd = remove_if(v.begin(), v.end(), f);
for(vector<int>::iterator it = f.evens.begin(); it != f.evens.end(); ++it)
{
cout<<*it<<"\n";
}
v.erase(newEnd, v.end());
return 0;
}
But this doesn't work as remove_if accepts the copy of my functor object, so the the stored evens vector is not accessible. What is the correct way of achieving this?
P.S. : The example, with even and odds is just for example sake, my real code is somethinf different. So don't suggest a way to identify even or odds differently.
The solution is not remove_if, but it's cousin partial_sort partition. The difference is that remove_if only guarantees that [begin, middle) contains the matching elements, but partition also guarantees that [middle, end) contains the elements which didn't match the predicate.
So, your example becomes just (note that evens is no longer needed):
vector<int>::iterator newEnd = partition(v.begin(), v.end(), f);
for(vector<int>::iterator it = newEnd; it != v.end(); ++it)
{
cout<<*it<<"\n";
}
v.erase(newEnd, v.end());
Your best bet is std::partition() which will rearrange all elts in the sequence such as all elts for which your predicate return true will precede those for which it returns false.
Exemple:
vector<int>::iterator bound = partition (v.begin(), v.end(), IsEven);
std::cout << "Even numbers:" << std::endl;
for (vector<int>::iterator it = v.begin(); it != bound; ++it)
std::cout << *it << " ";
std::cout << "Odd numbers:" << std::endl;
for (vector<int>::iterator it = bound; it != v.end(); ++it)
std::cout << *it << " ";
You can avoid copying your functor (i.e. pass by value) if you pass ist by reference like this:
vector<int>::iterator newEnd = remove_if(v.begin(), v.end(),
boost::bind<int>(boost::ref(f), _1));
If you can't use boost, the same is possible with std::ref. I tested the code above and it works as expected.
An additional level of indirection. Declare the vector locally, and
have IsEven contain a copy to it. It's also possible for IsEven to
own the vector, provided that it is dynamically allocated and managed by
a shared_ptr. In practice, I've generally found the local variable
plus pointer solution more convenient. Something like:
class IsEven
{
std::vector<int>* myEliminated;
public:
IsEven( std::vector<int>* eliminated = NULL )
: myEliminated( eliminated )
{
}
bool
operator()( int n ) const
{
bool results = n % 2 == 0;
if ( results && myEliminated != NULL ) {
myEliminated->push_back( n );
}
return results;
}
}
Note that this also allows the operator()() function to be const. I
think this is formally required (although I'm not sure).
The problem that I see with the code is that the evens vector that you create inside the struct gets created everytime the remove_if algorithm calls it. So no matter if you pass in a functor to remove_if it will create a new vector each time. So once the last element is removed and when the function call ends and comes out of the function the f.evens will always fetch an empty vector. This could be sorted in two ways,
Replace the struct with a class and declare evens as static (if that is what you wanted)
Or you could make evens global. I wouldn't personally recommend that( it makes the code bad, say no to globals unless you really need them).
Edit:
As suggested by nabulke you could also std::ref something likke this, std::ref(f). This prevents you from making the vector global and avoids for unnecessary statics.
A sample of making it global is as follows,
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
vector<int> evens;
struct IsEven
{
bool operator()(int n)
{
if(n % 2 == 0)
{
evens.push_back(n);
return true;
}
return false;
}
};
int main(int argc, char **argv)
{
vector<int> v;
for(int i = 0; i < 10; ++i)
{
v.push_back(i);
}
IsEven f;
vector<int>::iterator newEnd = remove_if(v.begin(), v.end(), f);
for(vector<int>::iterator it = evens.begin(); it != evens.end(); ++it)
{
cout<<*it<<"\n";
}
v.erase(newEnd, v.end());
return 0;
}
This code seems to work just fine for me. Let me know if this is not what you wanted.
You may have another solution; only if you don't need to remove elts in the same time (do you?). With std::for_each() which returns a copy of your functor. Exemple:
IsEven result = std::for_each(v.begin(), v.end(), IsEven());
// Display the even numbers.
std::copy(result.evens.begin(), result.evens.end(), std::ostream_iterator<int> (cout, "\n"));
Take note that it is always better to create unnamed variables in c++ when possible. Here that solution does not exactly answer your primary issue (removing elts from the source container), but it reminds everyone that std::for_each() returns a copy of your functor. :-)

Find nearest points in a vector

Given a sorted vector with a number of values, as in the following example:
std::vector<double> f;
f.pushback(10);
f.pushback(100);
f.pushback(1000);
f.pushback(10000);
I'm looking for the most elegant way to retrieve for any double d the two values that are immediately adjacent to it. For example, given the value "45", I'd like this to return "10" and "100".
I was looking at lower_bound and upper_bound, but they don't do what I want. Can you help?
EDIT: I've decided to post my own anser, as it is somewhat a composite of all the helpful answers that I got in this thread. I've voted up those answers which I thought were most helpful.
Thanks everyone,
Dave
You can grab both values (if they exist) in one call with equal_range(). It returns a std::pair of iterators, with first being the first location and second being the last location in which you could insert the value passed without violating ordering. To strictly meet your criteria, you'd have to decrement the iterator in first, after verifying that it wasn't equal to the vector's begin().
You can use STL's lower_bound to get want you want in a few lines of code. lower_bound uses binary search under the hood, so your runtime is O(log n).
double val = 45;
double lower, upper;
std::vector<double>::iterator it;
it = lower_bound(f.begin(), f.end(), val);
if (it == f.begin()) upper = *it; // no smaller value than val in vector
else if (it == f.end()) lower = *(it-1); // no bigger value than val in vector
else {
lower = *(it-1);
upper = *it;
}
You could simply use a binary search, which will run in O(log(n)).
Here is a Lua snippet (I don't have time to do it in C++, sorry) which does what you want, except for limit conditions (that you did not define anyway) :
function search(value, list, first, last)
if not first then first = 1; last = #list end
if last - first < 2 then
return list[first], list[last]
end
local median = math.ceil(first + (last - first)/2)
if list[median] > value then
return search(value, list, first, median)
else
return search(value, list, median, last)
end
end
local list = {1,10,100,1000}
print(search(arg[1] + 0, list))
It takes the value to search from the command line :
$ lua search.lua 10 # didn't know what to do in this case
10 100
$ lua search.lua 101
100 1000
$ lua search.lua 99
10 100
I'm going to post my own anser, and vote anyone up that helped me to reach it, since this is what I'll use in the end, and you've all helped me reach this conclusion. Comments are welcome.
std::pair<value_type, value_type> GetDivisions(const value_type& from) const
{
if (m_divisions.empty())
throw 0; // Can't help you if we're empty.
std::vector<value_type>::const_iterator it =
std::lower_bound(m_divisions.begin(), m_divisions.end(), from);
if (it == m_divisions.end())
return std::make_pair(m_divisions.back(), m_divisions.back());
else if (it == m_divisions.begin())
return std::make_pair(m_divisions.front(), m_divisions.front());
else
return std::make_pair(*(it - 1), *(it));
}
What if (in your case) d is less than the first element or more than the last? And how to deal with negative values? By the way: guaranteeing that your "d" lives between the first and the last value of your vector you can do like that:
// Your initializations
std::vector<double>::const_iterator sit = f.begin();
double upper, lower;
Here is the rest:
while ( *sit < d ) // if the element is still less than your d
++sit; // increase your iterator
upper = *sit; // here you get the upper value
lower = *(--sit); // and here your lower
Elegant enough? :/
You could do a search in your vector for your value (which would tell you where your value would be if it were in the vector) and then return the value before and after that location. So searching for 45 would tell you it should be at index=1 and then you would return 0 and 1 (depending on your implementation of the search, you'll either get the index of the smaller value or the index of the larger value, but this is easy to check with a couple boundary conditions). This should be able to run in O(log n) where n is the number of elements in your vector.
I would write something like this, didn't test if this compiles, but you get the idea:
template <typename Iterator>
std::pair<Iterator, Iterator> find_best_pair(Iterator first, Iterator last, const typename Iterator::value_type & val)
{
std::pair<Iterator, Iterator> result(last, last);
typename Iterator::difference_type size = std::distance(first, last);
if (size == 2)
{
// if the container is of size 2, the answer is the two elements
result.first = first;
result.first = first;
++result.first;
}
else
{
// must be of at lease size 3
if (size > 2)
{
Iterator second = first;
++second;
Iterator prev_last = last;
--prev_last;
Iterator it(std::lower_bound(second, last, val));
if (it != last)
{
result.first = it;
result.second = it;
if (it != prev_last)
{
// if this is not the previous last
// then the answer is (it, it + 1)
++result.second;
}
else
{
// if this the previous last
// then the answer is (it - 1, it)
--result.first;
}
}
}
}
return result;
}
I wrote up this little function, which seems to fit the more general case you wanted. I haven't tested it totally, but I did write a little test code (included).
#include <algorithm>
#include <iostream>
#include <vector>
template <class RandomAccessIt, class Container, class T>
std::pair<RandomAccessIt, RandomAccessIt> bracket_range(RandomAccessIt begin, RandomAccessIt end, Container& c, T val)
{
typename Container::iterator first;
typename Container::iterator second;
first = std::find(begin, end, val);
//Find the first value after this by iteration
second = first;
if (first == begin){ // Found the first element, so set this to end to indicate no lower values
first = end;
}
else if (first != end && first != begin) --first; //Set this to the first value before the found one, if the value was found
while (second != end && *second == val) ++second;
return std::make_pair(first,second);
}
int main(int argc, _TCHAR* argv[])
{
std::vector<int> values;
std::pair<std::vector<int>::iterator, std::vector<int>::iterator> vals;
for (int i = 1; i < 9; ++i) values.push_back(i);
for (int i = 0; i < 10; ++i){
vals = bracket_range(values.begin(), values.end(),values, i);
if (vals.first == values.end() && vals.second == values.end()){ // Not found at all
std::cout << i << " is not in the container." << std::endl;
}
else if (vals.first == values.end()){ // No value lower
std::cout << i << ": " << "None Lower," << *(vals.second) << std::endl;
}
else if (vals.second == values.end()) { // No value higher
std::cout << i << ": " << *(vals.first) << ", None Higher" << std::endl;
}
else{
std::cout << i << ": " << *(vals.first) << "," << *(vals.second) << std::endl;
}
}
return 0;
}
Based on the code that tunnuz posted, here you have some improvements regarding bound checking:
template<typename T>
void find_enclosing_values(const std::vector<T> &vec, const T &value, T &lower, T &upper, const T &invalid_value)
{
std::vector<T>::const_iterator it = vec.begin();
while (it != vec.end() && *it < value)
++it;
if(it != vec.end())
upper = *it;
else
upper = invalid_value;
if(it == vec.begin())
lower = invalid_value;
else
lower = *(--it);
}
Example of usage:
std::vector<int> v;
v.push_back(3);
v.push_back(7);
v.push_back(10);
int lower, upper;
find_enclosing_values(v, 4, lower, upper, -1);
std::cout<<"lower "<<lower<<" upper "<<upper<<std::endl;
If you have the ability to use some other data structure (not a vector), I'd suggest a B-tree. If you data is unchanging, I believe you can retrieve the result in constant time (logarithmic time at the worst).