Topic: Why no implicit conversion from Container to Iterator?


Author: Dean Brettle <brettle@picard.jmb.bah.com>
Date: 1995/06/12
Raw View
Forgive me if this is a FAQ.  Why is there no implicit conversion from a
container to an iterator "pointing to" the first object in the container?  This
seems important for writing generic algorithms which work on multi-level data
structures (i.e. containers of containers).  Consider the following short
program:


#include <vector.h>

// Define a generic function which we want to work on a container of
// containers.

template<class MajorIterator, class MinorIterator,
         class MajorDistance, class MinorDistance, class T>
void fill(MajorIterator majorStart, MinorIterator minorStart,
          MajorDistance majorN, MinorDistance minorN, const T& value)
{
  if (majorN==0 || minorN==0) return;
  MinorDistance n;
  MinorIterator minorFirst = *majorStart;
  distance(minorFirst, minorStart, n);
  for(MajorIterator major=majorStart; majorN--; major++)
    {
      MinorIterator minor = *major;
      advance(minor, n);
      MinorDistance count = minorN;
      for(; count--; minor++)
        {
           *minor = value;
        }
    }
}

// The above will not work on containers as they currently stand (see
// main below).  The only workaround I have been able to come up with is
// to derive a new class from the current containers which provides the
// implicit type conversion that is needed.  Something like the following
// may work.

template<class Container>
class better : public Container {
public:
  operator Container::const_iterator() const
  {
    return this->begin();
  }
};

// Here is a main() which illustrates the problem.

int main(int argc, char *argv[])
{
// The following is OK.
  int a[3][4];              // an array of arrays
  fill(a, a[0], 3, 4, 42);

// The following won't compile because *major is a vector<int> and there
// is no way of getting (*major).begin() within the template definition
// such that it will also work for arrays of arrays.
  vector<vector<int> > vv;   // a vector of vectors
  fill(vv.begin(), (*vv.begin()).begin(),
       vv.size(), (*vv.begin()).size(), 42);

// The following would be necessary to use the workaround described above.
  better<vector<better<vector<int> > > > bvbv; // Ick!
  fill(bvbv.begin(), (*bvbv.begin()).begin(),
       bvbv.size(), (*bvbv.begin()).size(), 42);
}


Why was this kind of conversion left out of the standard?  Or am I missing
something fundamental?

--Dean