[Insight-developers] itk::Array solutions
Brad King
brad.king@kitware.com
Thu, 25 Jan 2001 14:41:41 -0500 (EST)
Hello, all:
I have just checked in some changes to Array, Vector, and Point that
address the issues previously discussed.
1.) I changed the Vector constructor and assignment operator to take a
Vector instead of an Array (same for Point) so that Points and Vectors
cannot be directly assigned to one another. Now, an attempt to do that is
ambiguous due to three possible type conversions through Array::Reference,
Array::ConstReference, and Array::ValueType*
Unfortunately, this also prevents Point and Vector instances from being
set through assignment to Array instances. We might be able to solve this
by having Point and Vector privately inherit from Array, and duplicate ALL
of Array's public methods with pass-through calls. Any thoughts on this?
2.) Addressing the matlab-style array-fill:
Previously, we could do
itk::Vector<int, 4> v;
v = 5;
to set all elements in a vector, but the comma-separated list semantic
causes this to just initialize the first element. I have added two
methods to the Array class to address this:
itk::Vector<int, 4> v;
v.Fill(5);
// or
v = itk::Vector<int, 4>::Filled(5)
The Array class should be able to handle all ValueType settings, not just
numeric types, so it does not make sense to provide methods like
AssignZero() to do numerical assignment to array elements. Instead, we
can add itk namespace level functions to get all zeros:
itk::ArrayTools<int, 3>::Zeros()
or something like that could work. Thoughts?
3.) Ranged indexing. Jim requested the ability to use ranged indexing on
arrays (which carries over to points and vectors). The solution is
surprisingly clean, even in VC++. I have added an itk::Range class. It
is currently just in itkArray.h, but we should move it to its own file if
everyone likes its use. It should probably be renamed itk::StaticRange,
though, because it is a compile-time range selection class. Here is an
example:
itk::Array<int, 5> a;
itk::Array<int, 3> b;
a.Fill(0);
b.Fill(1);
a[itk::Range<1,3>()] = b;
// "a" will now contain {0,1,1,1,0}
itk::Array<int, 2> c = a[itk::Range<3,4>()];
// "c" will now contain {1,0}
the [] operator is templated over the beginning and end of the range. The
Range class doesn't hold anything at run-time. It is just there to tell
the compiler what template arguments to use when instantiating the []
operator, which then returns an Array::Reference to the portion of the
indexed array selected by the range. This results in compile-time range
size checking (can't assign a 4-component array to a 3-component range of
another array).
4.) Remaining issues...
Bounds checking on comma-separated list assignments:
I know that we can do compile time upper-bound checking using partial
specialization (not supported by VC++). There may be a way to do
lower-bound checking too, but I haven't looked into it yet. I can almost
guarantee there is no way to do either check at compile time in VC++. We
could consider using a COMPILER_SUPPORTS_PARTIAL_SPECIALIZATION macro to
turn the check on and off. This way we would get the check when testing
on systems with good enough compilers, but the fancy C++ code won't ruin
the ability of the code to compile on poor compilers. I don't think we
want to introduce such a macro, though, because it could be abused (for
example, used to turn features on/off). Thoughts?
Get_vnl_vector has been removed from itk::Array:
Since the Array class could be used to store non-numeric types, such as
"class X {};", and vnl_vector does not support these types, I had to
remove the Get_vnl_vector support. We could add it to itk::Vector
(probably a better place anyway), or we could create an itk namespace
level function to construct a vnl_vector_ref<> from an Array with a
numeric ValueType. Again, I'm looking for input on this.
-Brad