3

I have 3 iterators which belong to 3 vectors A, B and C. A function minn is called with these 3 iterators which returns the iterator with minimum value. Now how can i know which vector does the returned iterator minit belongs to? code -

vector<int>::iterator a = A.begin(), b = B.begin(), c = C.begin();
auto minit = minn(a,b,c);
smdsmkd
  • 41
  • 3
  • Does it matter? Why do you need this functionality? That may help better understand your problem. In any case, you can always use `std::pair`. – kabanus Jun 11 '18 at 06:59
  • 1
    You have to record it manually. See https://stackoverflow.com/q/11445025/5376789. – xskxzr Jun 11 '18 at 07:04
  • I need this so that i can increment that specific iterator which has the min value. – smdsmkd Jun 11 '18 at 07:08
  • What do you mean when you say *the iterator which has the minimum value*? Can you give a small example with a sample input ? Might be a [XY Problem](http://xyproblem.info/) – Vishaal Shankar Jun 11 '18 at 07:10
  • 1
    I need to compare the the 3 values, compute the difference of the max and min values of the 3 iterators and increment the one which is smallest and again follow the same steps till one of the iterators reaches the end of the vector. – smdsmkd Jun 11 '18 at 07:16

2 Answers2

1

The easiest option would be to not pass these iterators by value, so when you modify minit, whichever of a, b or c was chosen also changes.

bool itLess(std::vector<int>::iterator& l, std::vector<int>::iterator& r)
{
    return *l < *r;
}

for (
    auto a = A.begin(), b = B.begin(), c = C.begin(); 
    a != A.end() && b != B.end() && c != C.end();
    )
{
    auto [minit, maxit] = std::minmax({std::ref(a), std::ref(b), std::ref(c)}, itLess);
    // use minit.get() and maxit.get()
}

See it on coliru

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • The for loop + return by reference worked for me. Later I tried using the minmax function you used but it throws errors - "wrong number of template arguments (2, should be 1)" and "no matching function for call to ‘minmax::iterator&, bool(std::vector::iterator&, std::vector::iterator&)>(, bool (&)(std::vector::iterator&, std::vector::iterator&))’ " – smdsmkd Jun 11 '18 at 10:27
  • Ah, I was guessing syntax without a compiler handy. Switching to `std::reference_wrapper`s fixes it – Caleth Jun 11 '18 at 10:39
0

We can take advantage of the fact that vector stores its elements in a single continuous array. We can check if the element pointed by the iterator is located in memory between the beginning and the end of that array.

template<typename T>
bool isFromVector(const typename std::vector<T>::const_iterator &i, const std::vector<T> &v)
{
    const T *const dataBeginning = v.data();
    const T *const dataEnd = v.data() + v.size();
    const T *const element = &*i;
    return std::less_equal<const T*>()(dataBeginning, element) && std::greater<const T*>()(dataEnd, element);
}
Piotr Siupa
  • 3,929
  • 2
  • 29
  • 65
  • 1
    You can't do it like this, because `<=` and `>` are undefined for pointers from different arrays. You need to use `std::greater` and `std::less_equal` [`[expr.rel]`](http://eel.is/c++draft/expr.rel#3) – Caleth Jun 11 '18 at 08:59
  • @Caleth Looks like you are right: https://stackoverflow.com/a/9086675/3052438. Although, I suppose that normal operators work in most of situations and these clauses in standard are for the case of some unusual memory layouts. (I've tested my code.) Anyway, I'll improve my answer. – Piotr Siupa Jun 11 '18 at 09:18
  • @Caleth Done. Jeez, this syntax is weird. – Piotr Siupa Jun 11 '18 at 09:31
  • The syntax is nicer when they are used as parameters, especially with C++14, e.g. `std::sort(first, last, std::greater<>{})` – Caleth Jun 11 '18 at 09:39