Reputation: 688
How would you elegantly (and in a modern C++ way) write a function that returns the index of a vector element, taking as argument this vector, and a reference to one of its elements ?
Exceptions handling would be appreciated.
#include <vector>
template <class T>
std::size_t GetIndexFromRef(std::vector<T> &vec, T &item)
{
...
};
Upvotes: 3
Views: 870
Reputation: 63154
This does the trick:
template <class T>
std::size_t GetIndexFromRef(std::vector<T> const &vec, T const &item)
{
T const *data = vec.data();
if(std::less<T const *>{}(&item, data) || std::greater_equal<T const *>{}(&item, data + vec.size()))
throw std::out_of_range{"The given object is not part of the vector."};
return static_cast<std::size_t>(&item - vec.data());
};
I'm using std::less
and std::greater_equal
, because ([comparisons.general§2]):
For templates
less
,greater
,less_equal
, andgreater_equal
, the specializations for any pointer type yield a result consistent with the implementation-defined strict total order over pointers ([defns.order.ptr]).
[Note 1: Ifa < b
is well-defined for pointersa
andb
of typeP
, then(a < b) == less<P>()(a, b)
,(a > b) == greater<P>()(a, b)
, and so forth. — end note]
Otherwise, performing the comparison with an object that isn't part of the vector would be UB.
Upvotes: 7