we are testing some stl-compliant containers that have iterators on bits (as
vector<bool>) and we noticed some odd behaviour of iter_swap in different
stl implementations.
in visual studio 200x, iter_swap(i,j) performs swap(*i, *j).
but if *i is a proxy and not a real reference, this does not work:
we would have expected something not too intricated, but like this:
template <typename iter_t>
void iter_swap(iter_t a, iter_t b)
{
myswap(*a, *b, static_cast<std::iterator_traits<iter_t>::value_type*>(0) );
}
template <typename T, typenme V>
void myswap(T a, T b, V*)
{
// T is not a reference
V tmp = a;
a = b;
b = tmp;
}
template <typename T, typenme V>
void myswap(T& a, T& b, V*)
{
std::swap(a, b);
}
Obviously we had to specialize std::swap for CONST PROXY_T&, but we have the
vague feeling that this could be avoided. any comments?
typename...
> template <typename T, typenme V>
typename again... :)
Looking again at the code, I just realized it-s possibly ambiguous. I'll
test it, but I'm pretty sure this should do the trick:
template <typename T, typename V>
struct myswap
{
static void swap(T a, T b)
{
V tmp = a;
a = b;
b = tmp;
}
};
template <typename T, typename V>
struct myswap<T&, V>
{
static void swap(T& a, T& b)
{
std::swap(a, b);
}
};
template <typename iter_t>
void iter_swap(iter_t i, iter_t j)
{
typedef typename std::iterator_traits<iter_t>::value_type val_t;
typedef typename std::iterator_traits<iter_t>::reference ref_t;
myswap<ref_t, val_t>::swap(*i, *j);
}
This is an oxymoron. STL-compliant containers cannot have iterators on
bits. In particular, vector<bool> does not meet container requirements.
For more details, see
http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#96
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1999/n1185.pdf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2160.html
> in visual studio 200x, iter_swap(i,j) performs swap(*i, *j).
See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#187
> but if *i is a proxy and not a real reference, this does not work
... because i is not a forward iterator. See 24.1.3 table 74, which
requires that *i return a T&, where T is the value_type of the iterator.
> Obviously we had to specialize std::swap for CONST PROXY_T&, but we
> have the vague feeling that this could be avoided. any comments?
If you could specialize swap for your proxies, can't you also specialize
iter_swap for your "iterators"?
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
> This is an oxymoron. STL-compliant containers cannot have iterators on
> bits. In particular, vector<bool> does not meet container requirements.
> ... because i is not a forward iterator. See 24.1.3 table 74, which
> requires that *i return a T&, where T is the value_type of the iterator.
Thanks for the links; yes, I know the requirements, however I was just
pointing out that it's *possible* for
an stl implementation to work even when requirements are not strictly
satisfied (it can be by mere chance, but gcc stl does work correctly in our
case).
It may be possible, but it's not required. What better illustration than
discovering that your non-portable code does not, in fact, port?