Boost logo

Boost :

From: Kresimir Fresl (fresl_at_[hidden])
Date: 2001-09-05 08:04:15


On Wednesday 29 August 2001 19:50, walter_at_[hidden] wrote:

> > > Thanks a lot. I incorporated most of your changes and compiled
> > > with GCC 2.95.2. I hope, that we do not have to differentiate
> > > between 2.95.2 and 3.0.

Almost. Only remaining problem which I noticed is that the lines

   #ifdef USE_GCC
   namespace std {
       template<class I, class T>
       struct iterator {};
   }
   #endif

in `iterator.h' must be deleted (or commented out) to compile with 3.0.1.
(Also, there's no need for nonstandard definitions of `copy()' and
`swap_ranges()' in `config.h'. Were they really needed for 2.95?)

> > There's one more thing which I noticed in my examples:
> >
> >     matrix.h should include vector.h.

> Will be done, thanks for the hint.  

Still pending ;0)

There are some other missing includes:

  `vector_pr.h' in `matrix_pr.h'
  `matrix_pr.h' and `matrix.h' in `matrix_sp.h'
 
> > BTW, do you plan to add const versions of functions
> > matrix<>::row(), matrix<>::column() and matrix<>::project()
> > (which probably means introduction of corresponding
> > types const_matrix_row<> etc.) ?
>
> To understand the problem (and its consequences :-) I wrote a little
> sample. Here is a mutable vector range
>  
>     numerics::vector<double> v1 (1);
>     numerics::vector_range<numerics::vector<double> >
> vr1 (v1.project (0, 1));
>     vr1 (0) = 0;
>     std::cout << vr1 (0) << std::endl;
>  
> To get const correctness, you would like to write
>  
>     const numerics::vector<double> v2 (v1);
>     // numerics::vector_range<const numerics::vector<double> >
> // vr2 (v2.project (0, 1));
> // Compile time error: 2 overloads have no legal
> // conversion for 'this' pointer
>
> which is currently not possible. So if we extend
>  
> class vector {
>         // other stuff...
>  
>         typedef const vector<T, F, A> const_self_type;
>         typedef vector<T, F, A> self_type;
>         typedef vector_range<const_self_type> const_vector_range_type;
>         typedef vector_range<self_type> vector_range_type;
>  
>         const_vector_range_type project (size_type start,
> size_type stop) const;
>         vector_range_type project (size_type start, size_type stop);
>         const_vector_range_type project (const range &r) const;
>         vector_range_type project (const range &r);
>        
>         // more stuff...
> };
>
> the vector range is definable
>  
>     const numerics::vector<double> v2 (v1);
>     numerics::vector_range<const numerics::vector<double> >
> vr2 (v2.project (0, 1)); 
>     // vr2 (0) = 0; // Compile time error: Conversion loses qualifiers
>     // std::cout << vr2 (0) << std::endl;
> // Compile time error: Conversion loses qualifiers
>
> but access to the range does not compile. However a const vector range
>  
>     const numerics::vector<double> v3 (v1);
>     const numerics::vector_range<const numerics::vector<double> >
> vr3 (v3.project (0, 1));
>     // vr3 (0) = 0; // Compile time error: left operand must be l-value
>     std::cout << vr3 (0) << std::endl;
>
> should give us some kind of const correctness.

I think that `const_vector_range_type' can be defined as:

  template<...>
  class vector {
        // ...
        typedef const vector<T, F, A> const_self_type;
        typedef const vector_range<const_self_type>
                    const_vector_range_type;
        // ...
   };

and used as:

   const numerics::vector<double> cv (v);
   typename numerics::vector<double>::const_vector_range_type
        cvr (cv.project (b, e));

All legal (const) accesses are then possible.

(This is `VARIANT 1' of typedefs and functions that provide const
projections -- see below.)

> I currently would not like to introduce classes like
> const_vector_range, because that could result in more
> source code or more complex template constructions.

In fact, there's no need for new types (as I thought before).
Classes

  vector_expression_range<>
  matrix_vector_unary1<>
  matrix_vector_unary2<>
  matrix_expression_range<>

(which are return types of `global' project(), row() and column()
functions) can be used as return types of const member
functions:

  template <...>
  class vector {
        // ...      
        typedef vector<T, F, A> self_type;
        typedef typename
           vector_expression_range_traits<self_type>::result_type
           const_vector_range_type;
        // ...
        const_vector_range_type project (const range& r) const {
            return numerics::project (*this, r);
        }
        // ...
   };

I prefer this second variant; after all, these classes were obviously
designed to provide const projections.
 
Also, non-const projection classes (vector_range<>,
matrix_row<>, matrix_column<> etc.) can then be simplified.
For example, there is no need for const and non-const element
access operators:

  template <...>
  class vector_range {
      // ...
      value_type operator () (size_type i) const {
           // One has do to this, to get the const member dispatched?!
           const vector_type &data = data_;
           return data (r_ (i));
       }
       reference_type operator () (size_type i) {
           return data_ (r_ (i));
       }
       // ...
  };

(Quoted comment points to the problem.)
Const version (which returns non-const reference) suffices:

       reference_type operator () (size_type i) const {
           return data_ (r_ (i));
       }

This is similar to iterators: derefence operator is const although
it returns non-const reference to some element of a sequence.

I added const projection typedefs and functions to all (I hope)
relevant classes. Diff files (with respect to the latest version
in CVS) are attached, if you are interested. Both described variants
are included; eg.:

  template<...>
  class vector {
     // ...
     typedef vector<T, F, A> self_type;
  #ifdef NUMERICS_USE_VARIANT_1_CONST_VIEWS
     typedef vector<T, F, A> const const_self_type;
     typedef vector_range<const_self_type> const
        const_vector_range_type;
  #else
     typedef
        typename vector_expression_range_traits<self_type>::result_type
        const_vector_range_type;
   #endif
      // ...
  };

First variant does not work with canonical_vector<> and the
second with banded_matrix<>; strange, it seems that in both
cases the reason is that 'iterator' or 'const_iterator' are not
defined.

(Proposed changes to non-const projection classes are not
yet done.)

Sincerely,

fres




Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk