www.digitalmars.com         C & C++   DMDScript  

c++.stlsoft - [stlsoft][fixed_array_1d<>] size overhead

reply Thorsten Ottosen <nesotto cs.aau.dk> writes:
Hi Matthew,

I'm using the above class, but I was puzzled by the size occupied by the 
type (it was 12 bytes on my 32bit system).

I would like to get that down to 8 or 4 bytes. It turned out that the 
allocator (which the classes inherits from) takes up 4 bytes, even 
though it is in fact an empty class in many cases.

I think it should be possible to use something along boost's
compressed_pair:

http://www.boost.org/libs/utility/compressed_pair.htm

to hold the allocator and the size.

-Thorsten
Nov 30 2007
next sibling parent reply Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Hi Matthew,
 
Also, why does the classes not have a swap() member function? best regards -Thorsten
Dec 03 2007
next sibling parent reply Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true> (and similar for 2d, 3d, etc) The reason is that it makes it possible to return the view type fixed_array_1d<T, A, P, false> in a class hierarchy where some concrete classes uses, say, fixed_array_1d and some classes use fixed_array_2d. best regards -Thorsten
Dec 04 2007
next sibling parent reply Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true>
[Sorry for the spamming ... I don't know exactly what went wrong] There is another space optimization which is worth persuing: for fixed_array_1d<T, A, P, false> there is never a need to store an allocator (by deriving from it). I can submit a patch for all of these issues, if you agree on them. best regards -Thorsten
Dec 04 2007
next sibling parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
Please submit patch, and I'll integrate everything I don't disagree with.
:-)

btw, just for my information: what are you using them for? Something to do
with you PhD?

"Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
news:4755D786.3000702 cs.aau.dk...
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true>
[Sorry for the spamming ... I don't know exactly what went wrong] There is another space optimization which is worth persuing: for fixed_array_1d<T, A, P, false> there is never a need to store an allocator (by deriving from it). I can submit a patch for all of these issues, if you agree on them. best regards -Thorsten
Dec 08 2007
parent reply Thorsten Ottosen <nesotto cs.aau.dk> writes:
Matthew Wilson skrev:
 Please submit patch, and I'll integrate everything I don't disagree with.
 :-)
Ok, I'll look into it when I get some time.
 btw, just for my information: what are you using them for? Something to do
 with you PhD?
yes, I'm implementing 1d/2d probability tables as wrappers around these arrays. -Thorsten
 "Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
 news:4755D786.3000702 cs.aau.dk...
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true>
[Sorry for the spamming ... I don't know exactly what went wrong] There is another space optimization which is worth persuing: for fixed_array_1d<T, A, P, false> there is never a need to store an allocator (by deriving from it). I can submit a patch for all of these issues, if you agree on them. best regards -Thorsten
Dec 09 2007
parent reply Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Matthew Wilson skrev:
 Please submit patch, and I'll integrate everything I don't disagree with.
 :-)
Ok, I'll look into it when I get some time.
I don't have time to look at reimplementing compressed pair right now, but here are what I needed to implement operator=() on top of fixed_array1/2d. (I have only modified those two classes). I have added swap(T&), to allow implementing assignment by copy-and-swap. I have added non-const data(), to be able to memcopy to the buffer. I have made the constructor that takes a pointer, size public, as it allows one to move legacy buffers into the objects. I'm not really an expect on the allocator stuff, so I swap the allocators too (assuming that operation cannot throw). I know wg21 has been discussing allocators a lot lately, but I don't know the exact outcome and/or recommendations. To me this whole area seems serisouly difficult. cheers -Thorsten
Dec 09 2007
next sibling parent reply Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Matthew Wilson skrev:
 Please submit patch, and I'll integrate everything I don't disagree 
 with.
 :-)
Ok, I'll look into it when I get some time.
I don't have time to look at reimplementing compressed pair right now, but here are what I needed to implement operator=() on top of fixed_array1/2d. (I have only modified those two classes). I have added swap(T&), to allow implementing assignment by copy-and-swap.
My implementation of swap was buggy, although I couldn't quite figure out where it was. So I falied back on delegation to std::swap(), see attachment. -Thorsten
Dec 16 2007
parent "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
Weird. I just got around to implementing the data() and swap() methods, and
have done almost the same things as you for swap(). :-)

These changes will be with the next release (1.9.12). I am also hoping to
get to the others you've requested:
 * compressed inheritance issues
 * construction from a raw pointer
although I'd be happy to see how you might do these, as I'm not 100% sure
what you mean in the latter case.

"Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
news:fk3m3r$hcv$1 digitalmars.com...
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Matthew Wilson skrev:
 Please submit patch, and I'll integrate everything I don't disagree
 with.
 :-)
Ok, I'll look into it when I get some time.
I don't have time to look at reimplementing compressed pair right now, but here are what I needed to implement operator=() on top of fixed_array1/2d. (I have only modified those two classes). I have added swap(T&), to allow implementing assignment by
copy-and-swap.
 My implementation of swap was buggy, although I couldn't quite figure
 out where it was. So I falied back on delegation to std::swap(), see
 attachment.

 -Thorsten
---------------------------------------------------------------------------- ----
 *** fixed_array.hpp Fri Dec 14 22:45:20 2007
 --- fixed_array.hpp.original Tue Dec  4 23:43:27 2007
 ***************
 *** 103,109 ****

   #endif /* compiler */
   #include <stdexcept>                    // for std::out_of_range
 - #include <algorithm>                    // std::swap

   /*
/////////////////////////////////////////////////////////////////////////
    * Namespace
 --- 103,108 ----
 ***************
 *** 232,239 ****
   #endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */

   // Construction
 - public:
                     fixed_array_1d(T *data, index_type d0);
       ss_explicit_k fixed_array_1d(index_type d0);
                     fixed_array_1d(index_type d0, value_type const& t);
                     fixed_array_1d(class_type const& rhs);
 --- 231,238 ----
   #endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */

   // Construction
                     fixed_array_1d(T *data, index_type d0);
 + public:
       ss_explicit_k fixed_array_1d(index_type d0);
                     fixed_array_1d(index_type d0, value_type const& t);
                     fixed_array_1d(class_type const& rhs);
 ***************
 *** 288,296 ****

   // Access
   public:
 -     value_type              *data();
       value_type const        *data() const;
 -     void                     swap(class_type& other);

   // Implementation
   private:
 --- 287,293 ----
 ***************
 *** 303,310 ****

   // Members
   private:
 !     T *           m_data;
 !     index_type    m_d0;

       friend class fixed_array_2d<T, A, P, true>;
       friend class fixed_array_2d<T, A, P, false>;
 --- 300,307 ----

   // Members
   private:
 !     T * const           m_data;
 !     const index_type    m_d0;

       friend class fixed_array_2d<T, A, P, true>;
       friend class fixed_array_2d<T, A, P, false>;
 ***************
 *** 385,392 ****
   #endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */

   // Construction
 ! public:
       fixed_array_2d(T *data, index_type d0, index_type d1);
       fixed_array_2d(index_type d0, index_type d1);
       fixed_array_2d(index_type d0, index_type d1, value_type const& t);
       fixed_array_2d(class_type const& rhs);
 --- 382,390 ----
   #endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */

   // Construction
 ! private:
       fixed_array_2d(T *data, index_type d0, index_type d1);
 + public:
       fixed_array_2d(index_type d0, index_type d1);
       fixed_array_2d(index_type d0, index_type d1, value_type const& t);
       fixed_array_2d(class_type const& rhs);
 ***************
 *** 444,452 ****

   // Access
   public:
 -     value_type              *data();
       value_type const        *data() const;
 -     void                     swap(class_type& other);

   // Implementation
   private:
 --- 442,448 ----
 ***************
 *** 460,469 ****

   // Members
   private:
 !     T *           m_data;
 !     index_type    m_d0;
 !     index_type    m_d1;
 !     size_type     m_size;

       friend class fixed_array_3d<T, A, P, true>;
       friend class fixed_array_3d<T, A, P, false>;
 --- 456,465 ----

   // Members
   private:
 !     T * const           m_data;
 !     const index_type    m_d0;
 !     const index_type    m_d1;
 !     const size_type     m_size;

       friend class fixed_array_3d<T, A, P, true>;
       friend class fixed_array_3d<T, A, P, false>;
 ***************
 *** 805,810 ****
 --- 801,807 ----
   #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION

   // fixed_array_1d
 +
   template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
   inline ss_typename_type_k fixed_array_1d<T, A, P, R>::pointer
fixed_array_1d<T, A, P, R>::allocate_(ss_typename_type_k fixed_array_1d<T, A, P, R>::size_type n)
   {
 ***************
 *** 1081,1105 ****
   #endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */

   template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
 - inline ss_typename_type_k fixed_array_1d<T, A, P, R>::value_type *
fixed_array_1d<T, A, P, R>::data()
 - {
 -     return m_data;
 - }
 -
 - template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
   inline ss_typename_type_k fixed_array_1d<T, A, P, R>::value_type const*
fixed_array_1d<T, A, P, R>::data() const
   {
       return m_data;
   }

 ! template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
 ! inline void fixed_array_1d<T, A, P, R>::swap( fixed_array_1d& r )
 ! {
 !     std::swap( static_cast<allocator_type&>(*this),
 !                static_cast<allocator_type&>(r) );
 !     std::swap( m_data, r.m_data );
 !     std::swap( m_d0, r.m_d0 );
 ! }

   template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
   inline ss_typename_type_k fixed_array_2d<T, A, P, R>::pointer
fixed_array_2d<T, A, P, R>::allocate_(ss_typename_type_k fixed_array_2d<T, A, P, R>::size_type n)
 --- 1078,1090 ----
   #endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */

   template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
   inline ss_typename_type_k fixed_array_1d<T, A, P, R>::value_type const*
fixed_array_1d<T, A, P, R>::data() const
   {
       return m_data;
   }

 !
 ! // fixed_array_2d

   template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
   inline ss_typename_type_k fixed_array_2d<T, A, P, R>::pointer
fixed_array_2d<T, A, P, R>::allocate_(ss_typename_type_k fixed_array_2d<T, A, P, R>::size_type n)
 ***************
 *** 1431,1458 ****
   #endif /* STLSOFT_CF_BIDIRECTIONAL_ITERATOR_SUPPORT */

   template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
 - inline ss_typename_type_k fixed_array_2d<T, A, P, R>::value_type *
fixed_array_2d<T, A, P, R>::data()
 - {
 -     return m_data;
 - }
 -
 - template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
   inline ss_typename_type_k fixed_array_2d<T, A, P, R>::value_type const*
fixed_array_2d<T, A, P, R>::data() const
   {
       return m_data;
   }

 - template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
 - inline void fixed_array_2d<T, A, P, R>::swap(fixed_array_2d& other)
 - {
 -     std::swap( static_cast<allocator_type&>(*this),
 -                static_cast<allocator_type&>(other) );
 -     std::swap( m_data, other.m_data );
 -     std::swap( m_d0, other.m_d0 );
 -     std::swap( m_d1, other.m_d1 );
 -     std::swap( m_size, other.m_size );
 - }
 -
   // fixed_array_3d

   template <ss_typename_param_k T, ss_typename_param_k A,
ss_typename_param_k P, ss_bool_t R>
 --- 1416,1426 ----
Dec 16 2007
prev sibling parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
"Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
news:475C562A.3080909 cs.aau.dk...
 Thorsten Ottosen skrev:
 Matthew Wilson skrev:
 Please submit patch, and I'll integrate everything I don't disagree
with.
 :-)
Ok, I'll look into it when I get some time.
I don't have time to look at reimplementing compressed pair right now, but here are what I needed to implement operator=() on top of fixed_array1/2d. (I have only modified those two classes).
If you can, trying this on the 1.9.12 version - out soon - would be great.
 I have added swap(T&), to allow implementing assignment by copy-and-swap.
Done. Though the version I wrote approximates your newer version more than this one.
 I have added non-const data(), to be able to memcopy to the buffer.
Done.
 I have made the constructor that takes a pointer, size public, as it
 allows one to move legacy buffers into the objects.
Am not sure about this one, as I'm concerned that the ator might be asked to release something it did not allocate. Can you give me an example use case?
 I'm not really an expect on the allocator stuff, so I swap the
 allocators too (assuming that operation cannot throw). I know wg21 has
 been discussing allocators a lot lately, but I don't know the exact
 outcome and/or recommendations. To me this whole area seems serisouly
 difficult.
At the moment, we're just swapping the ator nature of the instances. If/when the ator "moves"/morphs, this may have to change. Cheers Matt
Dec 16 2007
parent Thorsten Ottosen <nesotto cs.aau.dk> writes:
Matthew Wilson skrev:
 "Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
 
 I have made the constructor that takes a pointer, size public, as it
 allows one to move legacy buffers into the objects.
Am not sure about this one, as I'm concerned that the ator might be asked to release something it did not allocate. Can you give me an example use case?
It's not something I would be using much personally, and many has the exact same reservationas as you. This is at least the feedback I got on this proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2225.html But, I do find it irritating when I work with a legacy program at work and try to use "modern" libraries, that I can't transfer buffers explicitly, and have to pay for copying an already existing buffer. Anyway, not something I have used for fixed_array yet. -Thorsten
Dec 17 2007
prev sibling parent "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
"Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
news:4755D786.3000702 cs.aau.dk...
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true>
[Sorry for the spamming ... I don't know exactly what went wrong] There is another space optimization which is worth persuing: for fixed_array_1d<T, A, P, false> there is never a need to store an allocator (by deriving from it). I can submit a patch for all of these issues, if you agree on them.
Am not sure this is going to be possible while retaining the wide compiler-compatiblity that the classes currently have. However, I'd be more than happy to give it a go. I'll try and release 1.9.12 tonight, and maybe you can patch your changes into the new version? Cheers Matt
Dec 16 2007
prev sibling parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
Can you give me a use case? I'm struggling to comprehend what you mean/want.

Thanks

Matt

"Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
news:4755D26E.5000106 cs.aau.dk...
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true> (and similar for 2d, 3d, etc) The reason is that it makes it possible to return the view type fixed_array_1d<T, A, P, false> in a class hierarchy where some concrete classes uses, say, fixed_array_1d and some classes use fixed_array_2d. best regards -Thorsten
Dec 16 2007
parent Thorsten Ottosen <nesotto cs.aau.dk> writes:
Matthew Wilson skrev:
 Can you give me a use case? I'm struggling to comprehend what you mean/want.
 
 Thanks
 
 Matt
 
 "Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
 news:4755D26E.5000106 cs.aau.dk...
 Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true> (and similar for 2d, 3d, etc) The reason is that it makes it possible to return the view type fixed_array_1d<T, A, P, false> in a class hierarchy where some concrete classes uses, say, fixed_array_1d and some classes use fixed_array_2d.
I needed to represent a slice or row of a matrix from a virtual function. Something along struct Table { typedef fixed_array_1d<T, A, P, false> view_type; virtual view_type get_conditional_probability( unsigned state ) = 0; }; struct Table1D : Table { ... } struct Table2D : Table { ... } Now, if I use fixed_array_2d<...>, I can return a view into a row as view_type, but that is not, AFAICT, possible from fixed_array_1d<....>, basically it should return a view of itself. Similarly for higher dimensions. What I did now was to create a custom view, storing a pointer and a size. -Thorsten
Dec 17 2007
prev sibling next sibling parent Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true> (and similar for 2d, 3d, etc) The reason is that it makes it possible to return the view type fixed_array_1d<T, A, P, false> in a class hierarchy where some concrete classes uses, say, fixed_array_1d and some classes use fixed_array_2d. best regards -Thorsten
Dec 04 2007
prev sibling next sibling parent Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true> (and similar for 2d, 3d, etc) The reason is that it makes it possible to return the view type fixed_array_1d<T, A, P, false> in a class hierarchy where some concrete classes uses, say, fixed_array_1d and some classes use fixed_array_2d. best regards -Thorsten
Dec 04 2007
prev sibling next sibling parent Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true> (and similar for 2d, 3d, etc) The reason is that it makes it possible to return the view type fixed_array_1d<T, A, P, false> in a class hierarchy where some concrete classes uses, say, fixed_array_1d and some classes use fixed_array_2d. best regards -Thorsten
Dec 04 2007
prev sibling parent Thorsten Ottosen <nesotto cs.aau.dk> writes:
Thorsten Ottosen skrev:
 Thorsten Ottosen skrev:
 Hi Matthew,
Also, why does the classes not have a swap() member function?
Furthermore, I find that it would be useful if one could construct fixed_array_1d<T, A, P, false> from fixed_array_1d<T, A, P, true> (and similar for 2d, 3d, etc) The reason is that it makes it possible to return the view type fixed_array_1d<T, A, P, false> in a class hierarchy where some concrete classes uses, say, fixed_array_1d and some classes use fixed_array_2d. best regards -Thorsten
Dec 04 2007
prev sibling next sibling parent "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
Thor

just want to let you know that I'm not ignoring. Will back to you in next
few days.

cheers

Matt

"Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
news:fiomkl$2koh$1 digitalmars.com...
 Hi Matthew,

 I'm using the above class, but I was puzzled by the size occupied by the
 type (it was 12 bytes on my 32bit system).

 I would like to get that down to 8 or 4 bytes. It turned out that the
 allocator (which the classes inherits from) takes up 4 bytes, even
 though it is in fact an empty class in many cases.

 I think it should be possible to use something along boost's
 compressed_pair:

 http://www.boost.org/libs/utility/compressed_pair.htm

 to hold the allocator and the size.

 -Thorsten
Dec 04 2007
prev sibling parent reply "Matthew Wilson" <matthew hat.stlsoft.dot.org> writes:
Have just done this (combining ator and m_data, btw). Just have to test it
on a whole bank of compilers.

This probably won't be in tonight's 1.9.12, but should be in 1.9.13 later in
the week.

Cheers

Matt

"Thorsten Ottosen" <nesotto cs.aau.dk> wrote in message
news:fiomkl$2koh$1 digitalmars.com...
 Hi Matthew,

 I'm using the above class, but I was puzzled by the size occupied by the
 type (it was 12 bytes on my 32bit system).

 I would like to get that down to 8 or 4 bytes. It turned out that the
 allocator (which the classes inherits from) takes up 4 bytes, even
 though it is in fact an empty class in many cases.

 I think it should be possible to use something along boost's
 compressed_pair:

 http://www.boost.org/libs/utility/compressed_pair.htm

 to hold the allocator and the size.

 -Thorsten
Dec 16 2007
parent Thorsten Ottosen <nesotto cs.aau.dk> writes:
Matthew Wilson skrev:
 Have just done this (combining ator and m_data, btw). Just have to test it
 on a whole bank of compilers.
 
 This probably won't be in tonight's 1.9.12, but should be in 1.9.13 later in
 the week.
No worries, we are not in that much of a hurry. -Thorsten
Dec 17 2007