[Lemon-user] [Lemon-devel] Array class proposal

Alpár Jüttner alpar at cs.elte.hu
Thu Jul 26 19:00:54 CEST 2012


Hi,

> >       * The declarations 'T1 t1' in the constructor parameter lists
> >         should be changed to 'T1 &t1' or 'const T1 &t1'. In fact, both
> >         versions should be implemented. Even worse, all possible
> >         combinations of const/non-const parameters should be
> >         implemented. Any idea how to do it correctly? Maybe a pair of
> >         recursive call of the constructor having one less parameters?
> I think, it's enough to have 'T1 &t1', if parameter g is const
> ListDigraph& then T1 will be evaluated as 'const ListDigraph'.

Unfortunately will not. For example

        class A 
        {
          int &a,
          int b;
        public:
          A(int &p,int q) : a(p), b(q) {}
        };
        ...
        int x;
        Array<A> a(12,x,14);

does not work unless the constructor 'T1 &t1, const T2 &t2' is there.

Regards,
Alpar

>  You can
> also check c++11 variadic template arguments feature, which can reduce
> the necessary code. Precompiler metaprogramming could be also used,
> but the code would be more complex than adding parameters up to N.
> 
> >       * The way how the memory block is allocated is wrong. Sometimes
> >         (not always it crashes at the call of delete []. Does anyone
> >         know how to correctly allocate a memory block which is to be
> >         deallocated by delete []?
> >         An alternative is the use std::allocator<>, but it seems to
> >         increase the memory footprint a bit.
> 
> I would use char array allocation and deallocation and call the
> destructor of the items directly:
> _array = reinterpret_cast<T*>(operator new char[size*sizeof(T)]);
> delete[] reinterpret_cast<char*>(_array);
> 
> The problem is with your code that a normal p = new T[n] returns a
> memory address for which
> *(reinterpret_cast<int*>(reinterpret_cast<T>(p) - sizeof(T*))) == n
> (it's not completely true for objects without destructor). So it
> allocates more memory than you did, and stores the array size in the
> first word - before the returned pointer. At the delete[] call, it
> tries to find this size information, which is missing in your
> implementation. Otherwise, the implementation can be compiler
> dependent, that's way I would not depend on it, and i would use the
> char* allocation.
> 
> 
> You need also handle exceptions in the constructors properly. If one
> of them breaks, then you have to call the destructor of the already
> constructed items, and then rethrow the exception.
> 
> Balazs
> 
> On Thu, Jul 26, 2012 at 4:06 PM, Alpár Jüttner <alpar at cs.elte.hu> wrote:
> > Two caveats concerning the array implementation of the previous mail:
> >
> >       * The declarations 'T1 t1' in the constructor parameter lists
> >         should be changed to 'T1 &t1' or 'const T1 &t1'. In fact, both
> >         versions should be implemented. Even worse, all possible
> >         combinations of const/non-const parameters should be
> >         implemented. Any idea how to do it correctly? Maybe a pair of
> >         recursive call of the constructor having one less parameters?
> >       * The way how the memory block is allocated is wrong. Sometimes
> >         (not always it crashes at the call of delete []. Does anyone
> >         know how to correctly allocate a memory block which is to be
> >         deallocated by delete []?
> >         An alternative is the use std::allocator<>, but it seems to
> >         increase the memory footprint a bit.
> >
> > Regards,
> > Alpar
> >
> >
> > On Thu, 2012-07-26 at 10:24 +0200, Alpár Jüttner wrote:
> >> Hi,
> >>
> >> It is a common problem that one would like use an array of objects, but
> >> (s)he can't because the object either (a) not default constructible or
> >> (b) not copyable. Notably, it is a regular question from LEMON users how
> >> to create an array of NodeMap<>.
> >>
> >> If the object is at least default constructible, than you can use
> >> new[]/delete[], otherwise (such as for NodeMap) the only reasonable
> >> solution is using std::vector<Object *> and manually and individually
> >> allocating/deleting the objects.
> >>
> >> Note, that even std::array introduced by C++11 fails to solve this
> >> problem, for (1) its size is determined compile-time, and (2) does not
> >> resolve (a).
> >>
> >> Instead, I propose another Array implementation, please find the
> >> prototype at the end of this mail.
> >>
> >> This is a fixed-size array, but the size is determined run time, i.e. at
> >> construction. Moreover, the objects in the array are constructed using
> >> the parameters passed to Array itself. Thus you can do this:
> >>
> >>         ListDigraph g;
> >>         ListDigraph::Node n;
> >>         ...
> >>         int size = 12;
> >>         Array<ListDigraph::NodeMap<int> > map_array(size, g);
> >>         map_array[2][n]=5;
> >>         map_array[3][n]+=11;
> >>
> >> or even:
> >>
> >>         Array<ListDigraph::NodeMap<bool> > map_array(size, g, true);
> >>         map_array[2][n]=false;
> >>
> >> What do you think of this idea? Does it worth including into LEMON?
> >>
> >> Plus a design question - do we need the _size member? Omitting it would
> >> be result in a narrower layer above the simple pointer it actually
> >> wraps. On the other, it allows a more stl-like interface with size(),
> >> iterators, begin(), end() etc. But to be honest, I see very little use
> >> of them here, except for size().
> >>
> >> Regards,
> >> Alpar
> >>
> >>
> >> // *****************************************************
> >> // * Array class                                       *
> >> // *****************************************************
> >>
> >>   template<class T >
> >>   class Array {
> >>     T * _array;
> >>     size_t _size;
> >>
> >>     ///Copying is not allowed.
> >>     Array(const Array &);
> >>     ///Copying is not allowed.
> >>     Array &operator=(const Array &);
> >>
> >>   public:
> >>     explicit Array(size_t size) : _array(new T[size]), _size(size) {}
> >>     template <class T1>
> >>     explicit Array(size_t size, T1 t1)
> >>       : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),
> >> _size(size)
> >>     {
> >>       for(size_t i=0;i<size;i++)
> >>       new (_array+i) T(t1);
> >>     }
> >>     template <class T1, class T2>
> >>     explicit Array(size_t size, T1 t1, T2 t2)
> >>       : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),
> >> _size(size)
> >>     {
> >>       for(size_t i=0;i<size;i++)
> >>       new (_array+i) T(t1,t2);
> >>     }
> >>     template <class T1, class T2, class T3>
> >>     explicit Array(size_t size, T1 t1, T2 t2, T3 t3)
> >>       : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),
> >> _size(size)
> >>     {
> >>       for(size_t i=0;i<size;i++)
> >>       new (_array+i) T(t1,t2,t3);
> >>     }
> >>     template <class T1, class T2, class T3, class T4>
> >>     explicit Array(size_t size, T1 t1, T2 t2, T3 t3, T4 t4)
> >>       : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),
> >> _size(size)
> >>     {
> >>       for(size_t i=0;i<size;i++)
> >>       new (_array+i) T(t1,t2,t3,t4);
> >>     }
> >>     template <class T1, class T2, class T3, class T4, class T5>
> >>     explicit Array(size_t size, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
> >>       : _array( static_cast<T*>(operator new[] (size*sizeof(T)))),
> >> _size(size)
> >>     {
> >>       for(size_t i=0;i<size;i++)
> >>       new (_array+i) T(t1,t2,t3,t4,t5);
> >>     }
> >>
> >>     ~Array() { delete [] _array; }
> >>     operator T* () { return _array; }
> >>     size_t size() { return _size; }
> >>   };
> >> }
> >>
> >>
> >> _______________________________________________
> >> Lemon-devel mailing list
> >> Lemon-devel at lemon.cs.elte.hu
> >> http://lemon.cs.elte.hu/mailman/listinfo/lemon-devel
> >>
> >>
> >>
> >> _______________________________________________
> >> Lemon-user mailing list
> >> Lemon-user at lemon.cs.elte.hu
> >> http://lemon.cs.elte.hu/mailman/listinfo/lemon-user
> >>
> >
> >
> > _______________________________________________
> > Lemon-user mailing list
> > Lemon-user at lemon.cs.elte.hu
> > http://lemon.cs.elte.hu/mailman/listinfo/lemon-user
> 





More information about the Lemon-user mailing list