Boost logo

Boost :

From: jsiek_at_[hidden]
Date: 2000-05-28 14:39:40


This is a nice idea... I think this approach works well for Blitz
arrays. However, my main problem with it is that it adds a lot of
complexity, and certainly some compile-time overhead compared to the
aggregate initialization. For a light-weight class like array I'm not
sure the benefits outweigh the costs.

Cheers,

Jeremy

Tomasz Kowalczyk writes:
> Nicolai Josuttis wrote:
> >
> > Hi Beman, hi all others,
> >
> > late but hopefully not too late attached here
> > is a new version of class array<>.
> > [..]
> > Comments are welcome.
> > Esspecially regarding the initialization stuff.
>
> I will try to add something constructive :)
>
> In the end of this mail, I have included an example of a technique which
> can be used to construct array elements with given arguments similarly
> to C array, and still be able to pass default value to initialize all
> the other elements, similarly to std::vector. This technique uses
> placement construction, like most std containers.
>
> Example how the usage may look like:
>
> // initialize first three elements of "a" explicitly, others to 0
> array<double,5> a = (var | -11, 'a', 56.2);
> // initialize first 4 elements of "b" explicitly, others to 100
> array<int,7> b( (var | 'q', 22UL, 0772, -12), 100 ) ;
>
> The name "var", and choice of operators "|" and "," are just my quick
> hack after a few attempts to make it look good. "var" serves as a seed
> for the list, and operators just fill that list.
>
> The main drawbacks I can see:
>
> 1. Array stores internally char[] and not T[]. However, there is no
> guarantee that internally stored char[] is properly aligned to store
> objects of type T. Unfortunately, I do not know of any C++ mechanism
> which would allow to enforce this and not call T's constructors at the
> same time.
> 2. Initialization function init_array_elements is called recursively.
> This can affect performance for many elements.
> 3. Initialization list (and generally all this example) will not compile
> without really good template specialization support.
> 4. Initialization list structure (named varlist here) does not fit well
> into a public interface of an array unless it is separately standarized.
>
> I was able to compile this code with egcs 1.1.2
>
> Tomasz
>
> /////////////////////////////////////////////////////////////////////////
>
> #include <memory>
> #include <new>
>
> struct nil;
>
> // A list with variables with varying types.
>
> template <class V, class N = nil>
> struct varlist
> {
> enum { pos = N::pos + 1 };
>
> typedef V value_type;
> typedef N next_type;
>
> value_type var;
> next_type next;
>
> varlist( value_type v, const next_type &n )
> : var(v)
> , next(n)
> {}
> };
>
> template <class V>
> struct varlist<V>
> {
> enum { pos = 0 };
>
> typedef V value_type;
> typedef nil next_type;
>
> value_type var;
>
> varlist( value_type v ) : var(v) {}
> };
>
>
>
> //
> // For convenient generation of variable reference lists, the
> // following syntax is introduced:
> //
> // (var | a,b,c)
> //
> // Creates a list of references for variables c,b,a (in this order).
> // The reverse order is enforced by the operator binding.
> //
>
> const struct varlist_seed { varlist_seed() {} } var;
>
> template <class A>
> varlist<A&> operator | ( const varlist_seed &, A &a ) {
> return varlist<A&>(a);
> }
>
> template <class A, class B, class C>
> varlist<C&,varlist<A,B> > operator , ( const varlist<A,B> &v, C & c ) {
> return varlist<C&,varlist<A,B> >(c,v);
> }
>
> template <class A>
> varlist<const A&> operator | ( const varlist_seed &, const A &a ) {
> return varlist<const A&>(a);
> }
>
> template <class A, class B, class C>
> varlist<const C&,varlist<A,B> > operator , ( const varlist<A,B> &v,
> const C & c ) {
> return varlist<const C&,varlist<A,B> >(c,v);
> }
>
>
> // Initialization of array elements from the varlist
>
> namespace detail {
> template <class T, class A, class V>
> void init_array_elements ( T * data, const varlist<A,V> &v ) {
> init_array_elements( data, v.next );
> new (data + varlist<A,V>::pos) T(v.var);
> }
>
> template <class T, class A>
> void init_array_elements ( T * data, const varlist<A,nil> &v ) {
> new (data) T(v.var);
> }
> }
>
>
> // Very limited array class, which is supposed to
> // ilustrate array element initialization
>
> template <class T, int N>
> class array {
> public:
>
> template <class U, class V>
> array( const varlist<U&,V> &v, const T &def = T() )
> {
> detail::init_array_elements( reinterpret_cast<T*>( data_ ), v );
>
> std::uninitialized_fill( data() + varlist<U&,V>::pos + 1,
> data() + N,
> def );
> }
>
> const T * data() const { return reinterpret_cast<const T*>(data_); }
> T * data() { return reinterpret_cast<T*>(data_); }
>
> int size() const { return N; }
>
> const T & operator [] ( int i ) const { return *(data() + i); }
> T & operator [] ( int i ) { return *(data() + i); }
>
> private:
> char data_[ sizeof(T) * N ];
> };
>
>
> // Simple test
>
> #include <iostream>
>
> template <class T, int N>
> ostream & operator << ( ostream &os, const array<T,N> &a )
> {
> os << "[";
> for (int i = 0; i < N; i++)
> os << " " << a[i];
> os << " ]";
> }
>
> main()
> {
> array<double,5> a = (var | -11, 'a', 56.2 );
> cout << a << endl; // [ -11 97 56.2 0 0 ]
>
> array<int,7> b( (var | 'q', 22UL, 0772, -12 ), 100 ) ;
> cout << b << endl; // [ 113 22 506 -12 100 100 100 ]
> }
>
> ------------------------------------------------------------------------
> Missing old school friends? Find them here:
> http://click.egroups.com/1/4055/3/_/9351/_/959525897/
> ------------------------------------------------------------------------
>
>
>


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