Hacker News new | ask | show | jobs
by mehrdadn 2527 days ago
With begin()/end() it's probably fine, but for-each loops it's not a great idea since then you run into problems when there was a cast intended. The main (only?) example of this pattern in the standard is vector<bool>, so of course people's immediate reaction to blame this on vector<bool>. However that's just the example currently in the standard, and people use it for other things too. By using auto you end up writing code that can break. Example:

  typedef std::vector<bool> Vec;
  Vec f(1, false);
  for (typename Vec::value_type &&x : f) { std::cout << typeid(x).name() << std::endl; }
  for (auto &&x : f) { std::cout << typeid(x).name() << std::endl; }
1 comments

Do you have examples of cases other than vector<bool> where this is an issue?
Thanks, those were interesting to read about. It doesn't seem like something that would come up in the for loop case, though.
I mean, you can imagine proxies for stuff beside bools and matrices...

  template<class It> struct iterator_range { It b, e; It begin() const { return b; } It end() const { return e; } };
  template<class It> iterator_range<It> make_iterator_range(It b, It e) { iterator_range<It> r = { b, e }; return r; }

  template<class T> struct endian_reversed_iterator {
   T *p;
   struct reference {
    T *p;
    operator T() const { return boost::endian::endian_reverse(*p); }
    reference &operator =(T const &other) const { *p = boost::endian::endian_reverse(other); }
   };
   endian_reversed_iterator(T *p) : p(p) { }
   reference operator *() { reference r = { p }; return r; }
   endian_reversed_iterator &operator++() { ++p; return *this; }
   bool operator!=(endian_reversed_iterator const &other) const { return p != other.p; }
  };

  int main() {
   unsigned arr[] = { 1, 2 };
   for (auto x : make_iterator_range<endian_reversed_iterator<unsigned> >(&arr[0], &arr[2])) {
    ++x;  // whatever
   }
  }