Boost logo

Boost :

From: Kresimir Fresl (fresl_at_[hidden])
Date: 2002-10-06 08:38:54

Toon Knapen wrote:

> For my ublas-to-blas bindings, I need to get hold of the internal-array. But
> to get the pointer to the first element, I still have some 'unexpected'
> failure : e.g.
> #include <boost/numeric/ublas/vector.hpp>
> int main()
> {
> boost::numeric::ublas::vector< double > v(3);
> const boost::numeric::ublas::vector< double >& cv( v ) ;
> const double* a = &cv[0] ; // 1: does not compile
> const double* b = &*cv.begin() ; // 2: does not compile
> const double* c = &* ; // 3: compiles
> return 0 ;
> }
> From the iterator_adaptor discussion, I learned that indeed 1 does not have
> to compile (if a ublas::vector is like a std::vector where operator[] is only
> required to return a type tha is convertible to T).

I am afraid that you got it wrong.

According to `Table 68 -- Optional sequence operations'
on pg 464 of the Standard, return type of the expression `a[n]',
where `a' is some *container* (and not an iterator), is
`reference' and for constant `a' `const_reference'.
And according to `Table 65 -- Container requirements',
(pg 460) return type of the expression `X::reference',
where ``X denotes a container class of containing objects
of type T'', is `lvalue of T' and of `X::const_reference'
`const lvalue of T'.

Also, definition of `std::vector<>' on pg 482 gives:

   template <class T, class Allocator>
   class vector {
      typedef typename Allocator::reference reference;
      typedef typename Allocator::const_reference const_reference;
      // ...
      reference operator[] (size_type n);
      const_reference operator[] (size_type n) const;
      // ...

And `Table 32 -- Allocator requirements', pg 356, defines the
return type of `X::reference' (`X' is now an allocator class)
to be `T&' and of `X::const_reference' `T const&'.

Iterators are another story. You are right -- return value
of `a[n]' (where `a' is *random access iterator*) should be
`convertible to T' (`Table 76 -- Random access iterator
requirements', pg 514). But in your expression `&cv[0]'
`cv' is not iterator.

> Case 2 however, I had expected that it would compile (AFAICT this is due to
> the fact that the iterator returns a const_reference which is _incorrectly_ a
> reference (uncommenting the following in the source makes it work)
> </begin ublas source snippet>
> // typedef const T &const_reference;
> typedef typename type_traits<T>::const_reference const_reference;
> </end ublas source snippet>

I think that you meant `_incorrectly_ a *value*'. Anyway,
I don't think it is incorrect.

Namely, question is whether `ublas::vector<>' must fulfill
standard container requirements (Table 65). If we require
it, then `const_reference' must be `T const&'. Currently,
for built-in types (e.g. `double') `const_reference' is `T'.
There are IMHO good efficiency reason for it:
in one of my benchmarks with `ublas::matrix<double>'
(compiled with g++ -O3) I got execution times
2.05, 1.63, 0.88, 0.39 when `const_reference' was
`double const&' and 1.78, 1.43, 0.6, 0.24' when it was
`double' -- there is noticeable difference.

Of course, although efficiency is important in numerical
code, it is not the only factor, so maybe I am wrong.

There is similar situation with `std::valarray<>'
(standard, pg 577):

     template <class T>
     class valarray {
         // ...
         T operator[] (size_t) const;
         T& operator[] (size_t);
          // ...

Issue 77 of ``C++ Standard Library Closed Issues List''
is why const version is not

     const T& operator[] (size_t) const;

Issue's status is ``NAD -- The LWG has reached consensus that the
issue is not a defect in the Standard'', but also ``Future -- In addition
to the regular status, the LWG believes that this issue should be
revisited at the next revision of the standard''.

There are advocates of both possibilities (`T' vs `T const&')
-- see, e.g. thread `proposal for resolution of "valarray operator[]
const returning value" (closed issue 77)' in `comp.std.c++'.

> As for case 3, I knew that matrices had a member data() for reasons we've
> long time ago discussed, but was not aware that the vectors supported it too.
> Anyway I'm glas I found it.

For more details on why and when it works (and also why
and when some other solutions do or don't work) see the
thread `ublas interoperability' in boost-ml.



Boost list run by bdawes at, gregod at, cpdaniel at, john at