Boost Array Initialization Technique

The fact that the Boost array class does not support constructors in favour of the limited and somewhat obscure aggregate initialization syntax has me concerned. IMO it would be much more flexible and powerful to support overloading of the comma operator. The following works on Visual C++ template<typename array_T, unsigned int N> struct array_comma_helper { array_comma_helper(array_T& x) : m(x) { } array_comma_helper(const array_comma_helper& x) : m(x.m) { } array_comma_helper& operator=(typename array_T::value_type x) { m[0] = x; return *this; } mutable array_T& m; }; template<class array_T, unsigned int N, class Scalar_T> array_comma_helper<array_T, N+1> operator,(array_comma_helper<array_T, N> h, const Scalar_T& x) { array_comma_helper<array_T, N+1> ret(h.m); ret.m[N + 1] = x; return ret; } template<class array_T> array_comma_helper<array_T, 0> initialize(array_T& x) { return array_comma_helper<array_T, 0>(x); } This enables us to write: int n = 2; array<int, 3> a; initialize(a) = 1, n, 3; This is much more flexible and it allows us to have constructors in boost::array thus making it a full reversible container. Christopher Diggins http://www.cdiggins.com

Did you see the Boost Assign Library: http://www.boost.org/libs/assign/index.html christopher diggins wrote:
The fact that the Boost array class does not support constructors in favour of the limited and somewhat obscure aggregate initialization syntax has me concerned. IMO it would be much more flexible and powerful to support overloading of the comma operator. The following works on Visual C++

----- Original Message ----- From: "Allen" <yaozhen@ustc.edu> To: <boost@lists.boost.org> Sent: Tuesday, May 31, 2005 1:29 PM Subject: [boost] Re: Boost Array Initialization Technique
Did you see the Boost Assign Library:
Yes. However, unless I am mistaken, it can only be used with back-insertable containers. There are of course other techniques than the one I proposed. My point is that I believe comma initialization to be superior to aggregate initialization, and that not making boost:array a conformant reversible container to be a mistake. Christopher Diggins

"christopher diggins" <cdiggins@videotron.ca> wrote in message news:007501c56609$1ff361f0$2b792518@heronnest... | ----- Original Message ----- | From: "Allen" <yaozhen@ustc.edu> | To: <boost@lists.boost.org> | Sent: Tuesday, May 31, 2005 1:29 PM | Subject: [boost] Re: Boost Array Initialization Technique | | | > Did you see the Boost Assign Library: | > | > http://www.boost.org/libs/assign/index.html | | Yes. However, unless I am mistaken, it can only be used with back-insertable | containers. There are of course other techniques than the one I proposed. My | point is that I believe comma initialization to be superior to aggregate | initialization, and that not making boost:array a conformant reversible | container to be a mistake. in the new boost, we might say array<int,5> a; a = cref_list_of<5>(1)(2)(3)(4)(5); if efficiency is important. Missing values are inserted as 0, and bounds are checked otherwise. The real benefit is of course when dealing with classes: struct X { X() {} X(int, int) {} }; array<X,4> a; a = list_of<X>(1,1)(1,2)(1,3)(1,4); -Thorsten

christopher diggins wrote:
The fact that the Boost array class does not support constructors in favour of the limited and somewhat obscure aggregate initialization syntax has me concerned. IMO it would be much more flexible and powerful to support overloading of the comma operator. The following works on Visual C++
<snip>
This is much more flexible and it allows us to have constructors in boost::array thus making it a full reversible container.
Are you saying you want boost::array to satisfy the requirements in Table 65? I think the postconditions for the expressions "X u" and "X()" will be hard to achieve. ;-) Jonathan

----- Original Message ----- From: "Jonathan Turkanis" <technews@kangaroologic.com> To: <boost@lists.boost.org> Sent: Tuesday, May 31, 2005 3:37 PM Subject: [boost] Re: Boost Array Initialization Technique
christopher diggins wrote:
The fact that the Boost array class does not support constructors in favour of the limited and somewhat obscure aggregate initialization syntax has me concerned. IMO it would be much more flexible and powerful to support overloading of the comma operator. The following works on Visual C++
<snip>
This is much more flexible and it allows us to have constructors in boost::array thus making it a full reversible container.
Are you saying you want boost::array to satisfy the requirements in Table 65?
I think the postconditions for the expressions "X u" and "X()" will be hard to achieve. ;-)
Not if the semantics were changed so that size() returned 0 when the array was unitialized (which I think would be an improvement). But fine, let's say that won't happen until heck freezes over, do you have an opinion on the fact that boost array has no constructors simply to support the rather obscure syntax of: boost::array a = { { 1, 2, 3; } } // notice two sets of { } Christopher Diggins

christopher diggins wrote:
----- Original Message ----- From: "Jonathan Turkanis" <technews@kangaroologic.com> To: <boost@lists.boost.org> Sent: Tuesday, May 31, 2005 3:37 PM Subject: [boost] Re: Boost Array Initialization Technique
christopher diggins wrote:
The fact that the Boost array class does not support constructors in favour of the limited and somewhat obscure aggregate initialization syntax has me concerned. IMO it would be much more flexible and powerful to support overloading of the comma operator. The following works on Visual C++
<snip>
This is much more flexible and it allows us to have constructors in boost::array thus making it a full reversible container.
Are you saying you want boost::array to satisfy the requirements in Table 65?
I think the postconditions for the expressions "X u" and "X()" will be hard to achieve. ;-)
Not if the semantics were changed so that size() returned 0 when the array was unitialized (which I think would be an improvement).
boost::array is just supposed to give built-in arrays a container interface. Built-in arrays never have size 0, so I don't see why boost::arrays should.
But fine, let's say that won't happen until heck freezes over, do you have an opinion on the fact that boost array has no constructors simply to support the rather obscure syntax of:
boost::array a = { { 1, 2, 3; } } // notice two sets of { }
compare: boost::array<int, 2> ar = { { 1, 2, 3 } }; with boost::array<int, 2> ar; initialize(ar) = 1, 2, 3; I like the first one.
Christopher Diggins
Jonathan

Jonathan Turkanis wrote:
christopher diggins wrote:
Not if the semantics were changed so that size() returned 0 when the array was unitialized (which I think would be an improvement).
boost::array is just supposed to give built-in arrays a container interface. Built-in arrays never have size 0, so I don't see why boost::arrays should.
Also, I think someone was telling me the other day how important it is that size is known at compile-time ;-)
Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:d7iigr$7tn$1@sea.gmane.org...
boost::array is just supposed to give built-in arrays a container interface. Built-in arrays never have size 0, so I don't see why boost::arrays should.
It would indicate that the array was not yet initialized and could help prevent erroneous use of uninitialized arrays. This behaviour is in fact implied by the fact that there exists an empty() function and separate size() and max_size() functions. The documentation IMO contradicts the intuitive interepretation of the class declaration.
compare:
boost::array<int, 2> ar = { { 1, 2, 3 } };
with
boost::array<int, 2> ar; initialize(ar) = 1, 2, 3;
I like the first one.
If operator=(T x) was defined then we could instead have the significantly better: boost::array<int, 2> ar; ar = 1, 2, 3; -- Christopher Diggins http://www.cdiggins.com

christopher diggins wrote:
"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:d7iigr$7tn$1@sea.gmane.org...
boost::array is just supposed to give built-in arrays a container interface. Built-in arrays never have size 0, so I don't see why boost::arrays should.
I forgot that array allows N = 0 as a special case. Anyway, it has a completely different meaning than "unitialized"
It would indicate that the array was not yet initialized and could help prevent erroneous use of uninitialized arrays. This behaviour is in fact implied by the fact that there exists an empty() function and separate size() and max_size() functions. The documentation IMO contradicts the intuitive interepretation of the class declaration.
Those functions are for consistency with the STL containers, as you mentioned before. I'm don't see the contradiction. Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:d7imf1$ka1$1@sea.gmane.org...
christopher diggins wrote:
"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:d7iigr$7tn$1@sea.gmane.org...
boost::array is just supposed to give built-in arrays a container interface. Built-in arrays never have size 0, so I don't see why boost::arrays should.
I forgot that array allows N = 0 as a special case. Anyway, it has a completely different meaning than "unitialized"
It would indicate that the array was not yet initialized and could help prevent erroneous use of uninitialized arrays. This behaviour is in fact implied by the fact that there exists an empty() function and separate size() and max_size() functions. The documentation IMO contradicts the intuitive interepretation of the class declaration.
Those functions are for consistency with the STL containers, as you mentioned before. I'm don't see the contradiction.
But it isn't an STL container! This so-called consistency is a dangerous illusion. Partial conformancy will lead to boost::array begin used in contexts where an STL container is expected but will instead cause the code to break silently because boost::array violates the container postconditions. Just for example consider the following common idiom: template<class Container_T> void some_very_dangerous_code(Container_T& x) { x = Container_T(); if (x.empty()} { SayHelloToAlphaCentauri(); } else { SendNukesToAlphaCentauri(); } } Obviously this will not work as expected. By explicitly *not* being consistent you avoid these headaches. You also don't confuse an intelligent yet inexpereienced programmer. My point is that Boost.Array can easily be conformant, or else it can be explicitly non-conformant, but somewhere in between is just asking for trouble. -- Christopher Diggins

christopher diggins wrote:
violates the container postconditions. Just for example consider the following common idiom:
template<class Container_T> void some_very_dangerous_code(Container_T& x) { x = Container_T(); if (x.empty()} { SayHelloToAlphaCentauri(); } else { SendNukesToAlphaCentauri(); } }
Obviously this will not work as expected.
What's expected here? Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> wrote in message news:d7j8it$1pt$1@sea.gmane.org...
christopher diggins wrote:
violates the container postconditions. Just for example consider the following common idiom:
template<class Container_T> void some_very_dangerous_code(Container_T& x) { x = Container_T(); if (x.empty()} { SayHelloToAlphaCentauri(); } else { SendNukesToAlphaCentauri(); } }
Obviously this will not work as expected.
What's expected here?
What was expected was that the SendNukesToAlphaCentauri() control path should never be executed BUT I made a big mistake (and a common one at that). I assumed x == y implied x.size() == y.size() for standard containers. That is not in fact an explicit postcondition of containers as far as I know. Since the example is unsatisfactory here is another: template<class Container_T> void some_very_dangerous_code() { Container_T x(); if (x.empty()} { SayHelloToAlphaCentauri(); } else { SendNukesToAlphaCentauri(); } } The point is not whether or not this is a good example but rather that incorrect and unexpected (possibly disastrous) behaviour will be exhibited in existing code by using a non-conformant container in a context where a conformant container is expected. -- Christopher Diggins http://www.cdiggins.com

On Tue, May 31, 2005 at 04:12:47PM -0400, christopher diggins wrote:
From: "Jonathan Turkanis" <technews@kangaroologic.com>
Are you saying you want boost::array to satisfy the requirements in Table 65?
I think the postconditions for the expressions "X u" and "X()" will be hard to achieve. ;-)
Not if the semantics were changed so that size() returned 0 when the array was unitialized (which I think would be an improvement). But fine, let's say that won't happen until heck freezes over, do you have an opinion on the fact that boost array has no constructors simply to support the rather obscure syntax of:
boost::array a = { { 1, 2, 3; } } // notice two sets of { }
IMHO it's one of the key features. To be usable where a C array is, but with a size() member to avoid range errors. It is also an intended feature of Austern's block template, which boost::array is partly inspired by. The standard is quite clear about what happens if the double braces are not present, so they are not required, if that's all you're concerned about. jon

On Tue, 31 May 2005 16:12:47 -0400, christopher diggins <cdiggins@videotron.ca> wrote: [...]
But fine, let's say that won't happen until heck freezes over, do you have an opinion on the fact that boost array has no constructors simply to support the rather obscure syntax of:
boost::array a = { { 1, 2, 3; } } // notice two sets of { }
"Simply"? This syntax allows you to initialize a const array. I typically use boost::array for constant lookup tables (often global), so I need to initialize the array this way. If you take this away boost::array would be useless the way I see it. -- Be seeing you.

christopher diggins wrote:
This is much more flexible and it allows us to have constructors in boost::array thus making it a full reversible container.
boost::array can never be a standard conforming container because it does not support insertion/removal of elements - it is a fixed size. When array was first proposed for TR1 we made suggestions to revise the container concepts to support both 'fixed size' and 'dynamic' containers. The consensus was that this was too much fiddling just to make array into a container. Instead, it was accepted as-is, as a 'container-like' class template. Aggregate initialization is an important part of the array concept, allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array. AlisdairM

----- Original Message ----- From: "AlisdairM" <alisdair.meredith@uk.renaultf1.com> To: <boost@lists.boost.org> Sent: Tuesday, May 31, 2005 7:52 PM Subject: [boost] Re: Boost Array Initialization Technique
christopher diggins wrote:
This is much more flexible and it allows us to have constructors in boost::array thus making it a full reversible container.
boost::array can never be a standard conforming container because it does not support insertion/removal of elements - it is a fixed size.
I believe the standard only requires insertion/removal of elements on sequences but not containers.
When array was first proposed for TR1 we made suggestions to revise the container concepts to support both 'fixed size' and 'dynamic' containers. The consensus was that this was too much fiddling just to make array into a container. Instead, it was accepted as-is, as a 'container-like' class template.
My points are that an alternative approach which would require less fiddling with the standard would have been to have uninitialized arrays have a size() of zero. Despite being not "array-like" it would help reduce the possibility of bugs. Furthermore as I pointed out in my previous post being "container-like" does more harm than good, because it simply can not be used safely where a container is expected, and leaves the dangerous illusion that it can. As a result, mixed messages will be sent to the programmers. I can just imagine the chaos that is going to erupt on the newsgroups if this gets into the standard as is: Newbie: array causes my existing code base for dealing with containers to break. Guru: array isn't a container Newbie: but it looks just like a container Guru: yes, it is container-like Newbie: what does that mean? Guru: it means that it looks like a container, but it shouldn't be used as a container Newbie: why was that done? Guru: *shrugs*
Aggregate initialization is an important part of the array concept,
I think precisely ust how important is debateable.
allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array.
Christopher Diggins http://www.cdiggins.com

"AlisdairM" <alisdair.meredith@uk.renaultf1.com> wrote in message news:d7itb3$6mk$1@sea.gmane.org...
Aggregate initialization is an important part of the array concept, allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array.
I know this is looking ahead quite a bit, but the next version of C++ is going to have a new meaning for the "auto" keyword. The code auto x = foo(); will declare x as a variable whose type is deduced from the return type of foo() (See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1794.pdf for details). It should be possible to use this to create a function that creates an array of the correct size: template <class T> array<T, 1> make_array(const T &t1); template <class T> array<T, 2> make_array(const T &t1, const T &t2); template <class T> array<T, 3> make_array(const T &t1, const T &t2, const T &t3); etc. Then we would be able to write code like auto my_array = make_array(1,2, 3); // The type of my_array is array<int, 3> Joe Gottman

AlisdairM a écrit :
Aggregate initialization is an important part of the array concept, allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array.
From my point of view, the main drawback is that in the following code: vector<double> v1(6); array<double, 6> v2; v1's content is initialized, v2's content is not. In fact, array is about the only class I know of that as a default constructor that does not initialize member data to a legal and documented value. This I strongly dislike. By the way, I also dislike the fact that double d; does not initialize d, but at least people know that fundamental type do not behave well when initialization is concerned. -- Loïc

On Wed, Jun 01, 2005 at 09:32:24AM +0200, Lo?c Joly wrote:
AlisdairM a ?crit :
Aggregate initialization is an important part of the array concept, allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array.
From my point of view, the main drawback is that in the following code:
vector<double> v1(6); array<double, 6> v2;
v1's content is initialized, v2's content is not. In fact, array is about the only class I know of that as a default constructor that does not initialize member data to a legal and documented value. This I strongly dislike.
This is true for any aggregate of builtins: struct S { char c; }; int i[5]; array is supposed to behave like an array. jon -- "Whenever you find that you are on the side of the majority, it is time to reform." - Mark Twain

Loïc Joly wrote:
From my point of view, the main drawback is that in the following code:
vector<double> v1(6); array<double, 6> v2;
v1's content is initialized, v2's content is not. In fact, array is about the only class I know of that as a default constructor that does not initialize member data to a legal and documented value. This I strongly dislike.
This was also mentioned during the standardisation process. I am more concerned that array< std::string, 6 > a1; array< double, 6 > a2; a1 inializes all its elements, a2 is not initialized at all.
By the way, I also dislike the fact that double d; does not initialize d, but at least people know that fundamental type do not behave well when initialization is concerned.
I hear you loud and clear! There is certainly a lot of work on the issue of initialization happening in the Standards committees right now, especially on the British panel. My interest in array is largely focussed on std::tr1 specification, and possibly adopting it in a future standard library. In that context, I do not want to see any changes until the language sorts out initialization in general.
From a Boost perspective: I am happier if array follows the TR1 specification, but should boost libraries be forever frozen once accepted into a standard TR? I am not sure on the answer to that.
AlisdairM

Loïc Joly wrote:
AlisdairM a écrit :
Aggregate initialization is an important part of the array concept, allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array.
From my point of view, the main drawback is that in the following code:
vector<double> v1(6); array<double, 6> v2;
v1's content is initialized, v2's content is not. In fact, array is about the only class I know of that as a default constructor that does not initialize member data to a legal and documented value. This I strongly dislike.
By the way, I also dislike the fact that double d; does not initialize d, but at least people know that fundamental type do not behave well when initialization is concerned.
I strongly disagree. Forcing initialization makes code that is not useful for high performance numerical processing. When we declare a container of 1000000 elements, we don't want to waste time initializing each, unless we want to. This is a serious defect in the current std::complex, IMHO.

----- Original Message ----- From: "Neal Becker" <ndbecker2@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, June 01, 2005 8:33 AM Subject: [boost] Re: Boost Array Initialization Technique
Loïc Joly wrote:
AlisdairM a écrit :
Aggregate initialization is an important part of the array concept, allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array.
From my point of view, the main drawback is that in the following code:
vector<double> v1(6); array<double, 6> v2;
v1's content is initialized, v2's content is not. In fact, array is about the only class I know of that as a default constructor that does not initialize member data to a legal and documented value. This I strongly dislike.
By the way, I also dislike the fact that double d; does not initialize d, but at least people know that fundamental type do not behave well when initialization is concerned.
I strongly disagree. Forcing initialization makes code that is not useful for high performance numerical processing. When we declare a container of 1000000 elements, we don't want to waste time initializing each, unless we want to.
I think the best solution in this case is to use an alternative "collection" for numerical processing. Using a class intended as general purpose array for numerical processing I think would not be a good idea. Christopher Diggins http://www.cdiggins.com

christopher diggins <cdiggins@videotron.ca> writes:
----- Original Message ----- From: "Neal Becker" <ndbecker2@gmail.com>
I strongly disagree. Forcing initialization makes code that is not useful for high performance numerical processing. When we declare a container of 1000000 elements, we don't want to waste time initializing each, unless we want to.
I think the best solution in this case is to use an alternative "collection" for numerical processing. Using a class intended as general purpose array for numerical processing I think would not be a good idea.
...because...? -- Dave Abrahams Boost Consulting www.boost-consulting.com

----- Original Message ----- From: "David Abrahams" <dave@boost-consulting.com> To: <boost@lists.boost.org> Sent: Wednesday, June 01, 2005 12:13 PM Subject: [boost] Re: Boost Array Initialization Technique
christopher diggins <cdiggins@videotron.ca> writes:
----- Original Message ----- From: "Neal Becker" <ndbecker2@gmail.com>
I strongly disagree. Forcing initialization makes code that is not useful for high performance numerical processing. When we declare a container of 1000000 elements, we don't want to waste time initializing each, unless we want to.
I think the best solution in this case is to use an alternative "collection" for numerical processing. Using a class intended as general purpose array for numerical processing I think would not be a good idea.
...because...?
I stated that far too strongly, sorry. My reasoning is that the implementation and interface of a numerical array could be optimized versus a general array. I would not design numerical arrays and general purpose arrays in the same way. For instance I would design a general purpose array to be default initialized, while I would permit a numerical array to be non-initialized. However, this is all moot because it is now perfectly clear to me that Boost.Array has the mandate to be as much like a built-in array as possible. Even if I do not particularly like that decision choice it is of course an acceptable choice to make. Making it a pseudo-container on the other hand is in my opinion a very big mistake. Christopher Diggins http://www.cdiggins.com

On Wed, Jun 01, 2005 at 01:07:25PM -0400, christopher diggins wrote:
----- Original Message ----- From: "David Abrahams" <dave@boost-consulting.com> To: <boost@lists.boost.org> Sent: Wednesday, June 01, 2005 12:13 PM Subject: [boost] Re: Boost Array Initialization Technique
christopher diggins <cdiggins@videotron.ca> writes:
----- Original Message ----- From: "Neal Becker" <ndbecker2@gmail.com>
I strongly disagree. Forcing initialization makes code that is not useful for high performance numerical processing. When we declare a container of 1000000 elements, we don't want to waste time initializing each, unless we want to.
I think the best solution in this case is to use an alternative "collection" for numerical processing. Using a class intended as general purpose array for numerical processing I think would not be a good idea.
...because...?
I stated that far too strongly, sorry. My reasoning is that the implementation and interface of a numerical array could be optimized versus a general array. I would not design numerical arrays and general purpose arrays in the same way. For instance I would design a general purpose array to be default initialized, while I would permit a numerical array to be non-initialized. However, this is all moot because it is now perfectly clear to me that Boost.Array has the mandate to be as much like a built-in
Actually, it's moot because it's been semi-standardised in TR1, not because you now understand the design goals ;)
array as possible. Even if I do not particularly like that decision choice it is of course an acceptable choice to make. Making it a pseudo-container on the other hand is in my opinion a very big mistake.
There are good reasons for that too, see the descriptions of Stroustrup's c_array and Austern's block for the basics. It's useful. Would you rather have an array type that cannot be used with STL-style algorithms, because it doesn't provide iterators? You've presented one argument against, namely that generic code that requires models of the container concept will misbehave when given a type that doesn't model the container concept. That's a simple violation of preconditions - which can be statically enforced with concept checks. jon -- "Simplicity is prerequisite for reliability." - Edsger Dijkstra

----- Original Message ----- From: "Jonathan Wakely" <cow@compsoc.man.ac.uk> To: <boost@lists.boost.org> Sent: Wednesday, June 01, 2005 1:36 PM Subject: Re: [boost] Re: Boost Array Initialization Technique
On Wed, Jun 01, 2005 at 01:07:25PM -0400, christopher diggins wrote:
I stated that far too strongly, sorry. My reasoning is that the implementation and interface of a numerical array could be optimized versus a general array. I would not design numerical arrays and general purpose arrays in the same way. For instance I would design a general purpose array to be default initialized, while I would permit a numerical array to be non-initialized. However, this is all moot because it is now perfectly clear to me that Boost.Array has the mandate to be as much like a built-in
Actually, it's moot because it's been semi-standardised in TR1, not because you now understand the design goals ;)
array as possible. Even if I do not particularly like that decision choice it is of course an acceptable choice to make. Making it a pseudo-container on the other hand is in my opinion a very big mistake.
There are good reasons for that too, see the descriptions of Stroustrup's c_array and Austern's block for the basics. It's useful. Would you rather have an array type that cannot be used with STL-style algorithms, because it doesn't provide iterators?
I don't mind iterators, and I do agree they are useful even in non-containers, but I do mind max_size() and empty(). They are there to make the container look like an STL container, though it doesn't behave as one. This is just plain misleading.
You've presented one argument against, namely that generic code that requires models of the container concept will misbehave when given a type that doesn't model the container concept. That's a simple violation of preconditions - which can be statically enforced with concept checks.
Good point, but I should point out very little existing code actually uses concept checks (at least for the time being, hopefully this will change soon). I am concerned that people will assume that max_size() and empty() exist to make Boost.Array an STL conformant container, which I think would be a very reasonable assumption!
jon
-Christopher Diggins

christopher diggins <cdiggins@videotron.ca> writes:
You've presented one argument against, namely that generic code that requires models of the container concept will misbehave when given a type that doesn't model the container concept. That's a simple violation of preconditions - which can be statically enforced with concept checks.
Good point, but I should point out very little existing code actually uses concept checks (at least for the time being, hopefully this will change soon). I am concerned that people will assume that max_size() and empty() exist to make Boost.Array an STL conformant container, which I think would be a very reasonable assumption!
jon
-Christopher Diggins
I think the risks are low. The standard Container concept is a very weak one that almost never shows up in generic code anyway. -- Dave Abrahams Boost Consulting www.boost-consulting.com

christopher diggins <cdiggins@videotron.ca> writes:
I stated that far too strongly, sorry. My reasoning is that the implementation and interface of a numerical array could be optimized versus a general array. I would not design numerical arrays and general purpose arrays in the same way. For instance I would design a general purpose array to be default initialized, while I would permit a numerical array to be non-initialized. However, this is all moot because it is now perfectly clear to me that Boost.Array has the mandate to be as much like a built-in array as possible. Even if I do not particularly like that decision choice it is of course an acceptable choice to make. Making it a pseudo-container on the other hand is in my opinion a very big mistake.
What use is it if you don't make it a pseudo-container? I mean, why not just use built-in arrays in that case? -- Dave Abrahams Boost Consulting www.boost-consulting.com

christopher diggins wrote:
----- Original Message ----- From: "Neal Becker" <ndbecker2@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, June 01, 2005 8:33 AM Subject: [boost] Re: Boost Array Initialization Technique
Loïc Joly wrote:
AlisdairM a écrit :
Aggregate initialization is an important part of the array concept, allowing it to act largely as a plug-in replacement for language arrays, with the bonus it can be passed by value as well as by reference. The main drawback here is that we cannot deduce the size of a boost::array, as you can with a language array.
From my point of view, the main drawback is that in the following code:
vector<double> v1(6); array<double, 6> v2;
v1's content is initialized, v2's content is not. In fact, array is about the only class I know of that as a default constructor that does not initialize member data to a legal and documented value. This I strongly dislike.
By the way, I also dislike the fact that double d; does not initialize d, but at least people know that fundamental type do not behave well when initialization is concerned.
I strongly disagree. Forcing initialization makes code that is not useful for high performance numerical processing. When we declare a container of 1000000 elements, we don't want to waste time initializing each, unless we want to.
I think the best solution in this case is to use an alternative "collection" for numerical processing. Using a class intended as general purpose array for numerical processing I think would not be a good idea.
I still disagree. Depending on default initialization is like depending on init of static variables to 0. If you really need a special init value, be explicit and say so. I see no logic to the default construct of complex to have 0 value. The only logic to default construct values I can see is where there truly is a sensible default for a parameter.

From: Neal Becker <ndbecker2@gmail.com>
I still disagree. Depending on default initialization is like depending on init of static variables to 0. If you really need a special init value, be explicit and say so. I see no logic to the default construct of complex to
What's wrong with relying on static initialization to get you a zero? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: Neal Becker <ndbecker2@gmail.com>
I still disagree. Depending on default initialization is like depending on init of static variables to 0. If you really need a special init value, be explicit and say so. I see no logic to the default construct of complex to
What's wrong with relying on static initialization to get you a zero?
Explicit is better than implicit. Have sympathy for those that must read the code. If you require something to be initialized, say so. Don't leave it to the reader to guess whether it had to be initialized to zero, or just was by accident.

From: Neal Becker <ndbecker2@gmail.com>
Rob Stewart wrote:
From: Neal Becker <ndbecker2@gmail.com>
I still disagree. Depending on default initialization is like depending on init of static variables to 0. If you really need a special init value, be explicit and say so. I see no logic to the default construct of complex to
What's wrong with relying on static initialization to get you a zero?
Explicit is better than implicit. Have sympathy for those that must read the code. If you require something to be initialized, say so. Don't leave it to the reader to guess whether it had to be initialized to zero, or just was by accident.
I fail to see how relying on behavior of the language is not having sympathy for those reading the code. This is akin to explicitly invoking a default base ctor in an initializer list in my mind. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
I fail to see how relying on behavior of the language is not having sympathy for those reading the code. This is akin to explicitly invoking a default base ctor in an initializer list in my mind.
Explicit is good. Consistent is also good. Consider: struct base { double a; }; struct derived1 : base { derived1() : base() {} }; struct derived2 : base { derived2() {} }; Which of the 2 derived classes do you think is more subtle? derived1, which initialized base so member a == 0.0, or derived2 which does not initialize base, so a could be anything including a troublesome NaN. Which would you rather call attention to by breaking with convention? And how many 'typical' C++ programmers do you believe are even aware of the difference? Relying (un-necessarily) on subtlety in the language, and trying to second guess whether it was intended or not, is generally a hard way to share code and an invitation for trouble in a shared-source environment. This thread is also heading off topic for a Boost list and would be more at home in comp.lang.c++.moderated. AlisdairM

From: "Alisdair Meredith" <alisdair.meredith@uk.renaultf1.com>
Rob Stewart wrote:
I fail to see how relying on behavior of the language is not having sympathy for those reading the code. This is akin to explicitly invoking a default base ctor in an initializer list in my mind.
Explicit is good.
Sometimes.
Consistent is also good.
Unless it isn't. (I *am* a big fan of consistency but, "A foolish consistency is the hobgoblin of little minds," as Emerson put it.)
Consider:
struct base { double a; };
struct derived1 : base { derived1() : base() {} };
I'd never invoke the default constructor of what was supposed to be POD. Indeed, doing so invokes default-initialization which is counter to the norm. Thus, not invoking the default ctor in the initializer list is better as I was making the case for previously.
struct derived2 : base { derived2() {} };
Which of the 2 derived classes do you think is more subtle? derived1, which initialized base so member a == 0.0, or derived2 which does not initialize base, so a could be anything including a troublesome NaN.
The former. It requires one to realize that it is invoking default-initialization and it "uglifies" the initializer list with the invocation of a default constructor. However, I don't care for the latter either.
Which would you rather call attention to by breaking with convention?
Neither. I'd write this: struct derived3 : base { derived3() { a = 0.0; } };
And how many 'typical' C++ programmers do you believe are even aware of the difference?
Few. Thus, derived3 is superior.
Relying (un-necessarily) on subtlety in the language, and trying to second guess whether it was intended or not, is generally a hard way to share code and an invitation for trouble in a shared-source environment.
static initialization is hardly a subtlety of the language.
This thread is also heading off topic for a Boost list and would be more at home in comp.lang.c++.moderated.
Reasonable. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

"Neal Becker" <ndbecker2@gmail.com> wrote
I still disagree. Depending on default initialization is like depending on init of static variables to 0. If you really need a special init value, be explicit and say so. I see no logic to the default construct of complex to have 0 value. The only logic to default construct values I can see is where there truly is a sensible default for a parameter.
A variable randomly initialised by the previous contents of the memory location will give random results. Default initialisation automatically gives a known repeatable value. regards Andy Little

| -----Original Message----- | From: boost-bounces@lists.boost.org | [mailto:boost-bounces@lists.boost.org] On Behalf Of Neal Becker | Sent: 01 June 2005 13:34 | To: boost@lists.boost.org | Subject: [boost] Re: Boost Array Initialization Technique | | Loïc Joly wrote: | | I strongly disagree. Forcing initialization makes code that | is not useful | for high performance numerical processing. When we declare a | container of | 1000000 elements, we don't want to waste time initializing | each, unless we | want to. | | This is a serious defect in the current std::complex, IMHO. I agree - but that NOT initialising should be the exception - so there needs to be a way of saying "I really don't want this to be initialised". Paul Paul A Bristow Prizet Farmhouse, Kendal, Cumbria UK LA8 8AB +44 1539 561830 +44 7714 330204 mailto: pbristow@hetp.u-net.com
participants (15)
-
Alisdair Meredith
-
AlisdairM
-
Allen
-
Andy Little
-
christopher diggins
-
David Abrahams
-
Joe Gottman
-
Jonathan Turkanis
-
Jonathan Wakely
-
Loïc Joly
-
Neal Becker
-
Paul A Bristow
-
Rob Stewart
-
Thore Karlsen
-
Thorsten Ottosen