Topic: Using vector of vectors


Author: "E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov>
Date: 22 Jun 2002 00:35:36 GMT
Raw View
John Potter wrote:

> E. Robert Tisdale wrote:
>
> > aran@100acres.ws wrote:
> >
> > > E. Robert Tisdale wrote:
> > >
> > > >           const
> > > >           int   N = 4;
> > > >           const
> > > >           int   C = 3;
> > > >           using std::vector;
> > > >           vector<vector<double> > distanze(N, C);
> > > >
> > > > Did you get different results from your compiler?
> > >
> > > Yes.
>
> Your compiler is broken.
>
> > > You are depending on a missing explicit in your stl code.  Your
> > >
> > >     vector<vector<double> > distanze(N, C);
>
> No.  Your compiler is likely missing member template support or
> your library was written under that assumption.  That statement matches
>
>    template <class InputIterator>
>    vector<vector<double> > (InputIterator N, InputIterator C)
>
> Overload resolution is totally ignorant of the intent of InputIterator.
> Two ints matches.  Since this problem was well known,
> 23.1.1/9 requires that
> when InputIterator is an integral type that it behave as
>
>    vector<vector<double> > (static_cast<size_type>(N),
>          static_cast<vector<double> >(C));
>
> The static_cast makes the value_type construction explicit.

James Kanze wrote:

> aran@100acres.ws wrote:
>
> > E. Robert Tisdale wrote:
> >
> > > aran@100acres.ws wrote:
> > >
> > > > E. Robert Tisdale wrote:
> > > >
> > > > > Did you get different results from your compiler?
> > > >
> > > > Yes.
> > > >
> > > > You are depending on a missing explicit in your stl code.  Your
> > > >
> > > >     vector<vector<double> > distanze(N, C);
> > > >
> > > > is being automatically converted to
> > > >
> > > >     vector<vector<double> > distanze(N, vector<double>(C));
> > > >
> > > > by the compiler.
> > > > That constructor should be explicit and apparently is not in your
library.
> > > >
> > > > (see 23.2.4.2 of the 1998 C++ spec)
> > >
> > > In /usr/include/g++-v3/bits/stl_vector.h
> > >
> > >         template <class _Tp, class _Alloc = allocator<_Tp> >
> > >         class vector : protected _Vector_base<_Tp, _Alloc> {
> > >           // [snip]
> > >         public:
> > >           // [snip]
> > >           explicit vector(size_type __n): _Base(__n, allocator_type())
{
> > >             _M_finish = uninitialized_fill_n(_M_start, __n, _Tp());
> > >             }
> > >           // [snip]
> > >           };
> >
> > Wow, you're right.
> > I checked this at work (we're using g++)
> > and the constructor that gets called is:
> >
> >     template <class Iterator>
> >     vector(Iterator b, Iterator e);
>
> Which is as it should be.  See 23.1.1/9.
>
> On the other hand,
> I (and I suspect some others) don't like the fact that
> this clause hides a static_cast, which in turn "undoes" an "explicit".
> Ideally, we'd like it to act as if there was
> an attempt to call the (size_t,T const&) constructor.
>
> > There is a special check in the g++ library
> > if Iterator is an integral type to explicitly construct the contained
type.
> >
> > This is by no means a standard feature of standard STL
> > (i.e. non-portable).  It's actually some interesting code.
>
> The trick is interesting.  But it is quite standard
> and required for a library to be conforming.

So who is correct here?  John Potter?  Or James Kanze?

Is my GNU C++ compiler [standard library] correct?
Or should I file a bug report?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Sun, 23 Jun 2002 21:24:53 CST
Raw View
On 22 Jun 2002 00:35:36 GMT, "E. Robert Tisdale"
<E.Robert.Tisdale@jpl.nasa.gov> wrote:

> John Potter wrote:
> > E. Robert Tisdale wrote:
> > > aran@100acres.ws wrote:
> > > > E. Robert Tisdale wrote:
> > > > > Did you get different results from your compiler?
> > > > Yes.
> > Your compiler is broken.

Note that it is aran's compiler that is broken.

> So who is correct here?  John Potter?  Or James Kanze?

Since we agree, that is easy. :)

> Is my GNU C++ compiler [standard library] correct?

The library is correct.

Here is a simple case which might help to see why it is needed.

vector<int> v(5, 7);

The (iter, iter) ctor wins over the (size_type, int) ctor.  We would
not want this to fail.  This would work with only one static_cast.

vector<int> v(vector<int>::size_type(5), 7);

Solves the problem, but is at least awkward.

vector<double> v(5, 7);

Again, the (iter, iter) ctor and something must be cast.

vector<double> v(5, 7.);

Solves the problem, and is not too bad.  If the special rule
were not there, the error message from the missing period should
be stressful for a beginner.

The fact that it works in the two dimensional case may be an accident
and it does not extend to three dimensions.

vector<double, vector<double> > v(5, vector<double>(7));

Solves the problem, and seems appropriate to me.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: Thu, 20 Jun 2002 23:12:19 GMT
Raw View
On Thu, 20 Jun 2002 17:26:56 GMT, "E. Robert Tisdale"
<E.Robert.Tisdale@jpl.nasa.gov> wrote:

> aran@100acres.ws wrote:

> > "E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov> writes:

> > >           const
> > >           int   N = 4;
> > >           const
> > >           int   C = 3;
> > >           using std::vector;
> > >           vector<vector<double> > distanze(N, C);

> > > Did you get different results from your compiler?

> > Yes.

Your compiler is broken.

> > You are depending on a missing explicit in your stl code.  Your
> >
> >     vector<vector<double> > distanze(N, C);

No.  Your compiler is likely missing member template support or your
library was written under that assumption.  That statement matches

   template <class InputIterator>
   vector<vector<double> > (InputIterator N, InputIterator C)

Overload resolution is totally ignorant of the intent of
InputIterator.  Two ints matches.  Since this problem was well known,
23.1.1/9 requires that when InputIterator is an integral type that it
behave as

   vector<vector<double> > (static_cast<size_type>(N),
         static_cast<vector<double> >(C));

The static_cast makes the value_type construction explicit.

John

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov>
Date: Thu, 20 Jun 2002 17:26:56 GMT
Raw View
aran@100acres.ws wrote:

> "E. Robert Tisdale" <E.Robert.Tisdale@jpl.nasa.gov> writes:
>
> > John Harrison wrote:
> >
> > > I think you mean
> > >
> > > vector<vector<double> > distanze(N, vector<double>(C));
> >
> > Nope.
> >
> >         $ cat main.cc
> >         #include<iostream>
> >         #include<iomanip>
> >         #include<vector>
> >
> >         int
> >         main(int argc, char* argv[]) {
> >           const
> >           int   N = 4;
> >           const
> >           int   C = 3;
> >           using std::vector;
> >           vector<vector<double> > distanze(N, C);
> >
> >           for (int j = 0; j < N; ++j)
> >             for (int k = 0; k < C; ++k)
> >               distanze[j][k] = k + j*10;
> >
> >           std::cout << "distanze =" << std::endl;
> >           for (int j = 0; j < N; ++j) {
> >             for (int k = 0; k < C; ++k)
> >               std::cout << ' ' << std::setw(2) << distanze[j][k];
> >             std::cout << std::endl;
> >             }
> >           return 0;
> >           }
> >
> >         $ g++ -O2 -ansi -pedantic -Wall -o main main.cc
> >         $ ./main
> >         distanze =
> >           0  1  2
> >          10 11 12
> >          20 21 22
> >          30 31 32
> >
> > Did you get different results from your compiler?
>
> Yes.
>
> You are depending on a missing explicit in your stl code.  Your
>
>     vector<vector<double> > distanze(N, C);
>
> is being automatically converted to
>
>     vector<vector<double> > distanze(N, vector<double>(C) );
>
> by the compiler.
>  That constructor should be explicit and aparently is not in your library.
>
> (see 23.2.4.2 of the 1998 C++ spec)

In /usr/include/g++-v3/bits/stl_vector.h

        template <class _Tp, class _Alloc = allocator<_Tp> >
        class vector : protected _Vector_base<_Tp, _Alloc> {
          // [snip]
        public:
          // [snip]
          explicit vector(size_type __n): _Base(__n, allocator_type()) {
            _M_finish = uninitialized_fill_n(_M_start, __n, _Tp());
            }
          // [snip]
          };

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]