|
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 = &*cv.data().begin() ; // 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 {
public:
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 {
public:
// ...
T operator[] (size_t) const;
T& operator[] (size_t);
// ...
};
Issue 77 of ``C++ Standard Library Closed Issues List''
(http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/lwg-closed.html#77)
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.
Sincerely,
fres
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk