On Jul 17, 2008, at 3:19 PM, Ronald Garcia wrote:
On Jul 11, 2008, at 6:17 AM, Dr Johann A. Briffa wrote:
I realize this topic has been discussed before (I've seen at least a thread in 2006 and another in 2007), but I believe there is more to add. At issue is the decision that multi_array objects cannot be assigned [with the operator=() that is] unless the target is already the same size as the source. Further, there is no documented way to easily resize an existing array to the same size and range as some other array.
Indeed there is no built-in way to easily resize a multi_array to be the same size as another multi_array. While there is no resize member function that takes a pointer, there is one that takes a model of the Collection concept (classes like boost::array and std::vector are concepts). Based on this interface, here is a stop- gap non-invasive solution that can resize a multi_array based on another model of MultiArray (multi_array, multi_array_ref, etc.): [TRUNCATE]
Let's define some stuff here: T: some type you created, probably a class type a: an object of type T; it's valid, i.e. meets its invariants b: another object of type T, also valid; any similarities or differences in its state from a's state is unspecified C: the set of all valid states an object of type T may have Let function F: x -> Y, map a T object state x to a (sub)set of C named Y. This function returns the subset of source states that a given state can receive during an assignment. If there exists at least one x in C such that F(x) = Y < C, then type T is _NOT_ Assignable! In other words, the number of assignment- compatibility classes in T must be exactly one for T to be Assignable. Furthermore, an Assignable type requires that the destination object's observable state post-assignment matches the observable state of the source object. The destination's new state can't be the old state quasi-merged with the source's state. (The destination object's old state must appear to be splattered, but remnants could be cached to the new state.) Fortunately, most types are Assignable. What happens if your type isn't? 1. Users can't use objects of that type in standard containers, which assume to be able to freely copy objects as much as they want. 2. Such objects are a pain to work with. Any containing class must write custom assignment operators to add calls to your custom copying routine. Of course, they have to first check if the source and destination objects are in the same assignment-compatibility class, and reconfigure at least one of those two objects if they're not in the same class. The exception would be if the wrapping class always makes sure that every T object it creates is of the same class. Even that is a pain because the user has to manually confirm that invariant every time s/he changes or adds a mutating function. 3. It isn't safe. You are effectively dumping the responsibility of assignment onto your users, who won't have all the information. The user generally has to test compatibility, reconfigure at least one object, then do call the custom copying routine. These steps are distinct, so if one of the mutating steps throws, the user will probably lose his/her old state forever and have a default-valued object. Your assignment routine would have more information available, so it can structure the assignment with roll-back during throws. (This could be moderated with a swap routine that doesn't care about assignment-compatibility classes. You do have a custom swap, right? And it does work irrespective of class, right?!) -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com