Re: OONSTD: Standard Names

E. Robert Tisdale (edwin@maxwell.hrl.hac.com)
Fri, 10 Jul 1998 17:12:24 -0700 (PDT)

> At 01:23 PM 7/10/98 -0700, E. Robert Tisdale wrote:
>>Eventually, we must agree upon standard names for classes and functions.

Actually, I said,

"Eventually, we must agree upon standard names for classes and functions.
Then, once we have decided the meaning of each standard class and function,
the library developer will be able to provide a reliable interface
to the application programmer. No matter how we choose these names,
no application programmer will ever be totally pleased with them. That's OK.
The application programmer will simply include a header file which uses
typedef to rename the classes and inline functions to rename the functions."

> Why? This might have been useful in C++ prior to templates,
> but generic programming really offers a much more flexible approach.
> Straight-forward generic programming would template algorithms
> on the "Matrix" and "Vector" types and assume a particular interface
> for these types (standard "function" names).
> However, one can use traits to provide an additional level of indirection
> (compile-time indirection) so standard function names are not even required,
> just a particular set of capabilities.
> I highly recommend that you take a look at Geoff Furnish's recent paper
> on this subject in this month's Computers In Physics.

I read Geoff's paper very carefully before sending the email you reference.

> For instance, all of the standard function names that you discuss
> become standard traits in the library's traits class:
>
> template <class Matrix>
> struct MatrixTraits { };
>
> template <>
> struct MatrixTraits<doubleMatrix> {
> typedef doubleMatrix Mat_t;
> typedef doubleMatrix::Handle Handle_t;
> static Handle_t handle(const Mat_t &m) { return m.handle(); }
> static int offset(const Mat_t &m) { return m.offset(); }
> static int stride1(const Mat_t &m) { return m.stride1(); }
> static int length1(const Mat_t &m) { return m.length1(); }
> // etc.
> };
>
> The algorithms then template off the Matrix type and perform all operations
> on Matrix objects through the MatrixTraits members.
> For instance, here is a really trivial example:
>
> template <class Matrix>
> void transpose(Matrix &a) {
> typedef MatrixTraits<Matrix> MT;
> int i_start = MT::begin1(a);
> int i_end = MT::end1(a);
> int j_start = MT::begin2(a);
> int j_end = MT::end2(a);
> assert(j_end-j_start == i_end-i_start);
>
> for (int i = i_start; i < i_end; ++i)
> for (int j = j_start; j < j_end; ++j)
> swap(a(i,j), a(j,i));
> }
>
> This will work with any "Matrix" class that has operator() overloaded
> for indexing (one "standard" that we should all implement) and that has
> specialized MatrixTraits to provide the begin1(), etc., operations.

It appears to me that you have done exactly what I would expect
an application programmer would do.
Personally, I don't care for the method you chose.
I think it is ugly and unnecessarily complicated.
If the library developers must supply the definition of MatrixTraits,
then they will need to have standard names.
If the definition of MatrixTraits is left to application programmers,
it would be easier to rename all the types and functions.

> So, rather than standardizing on names for classes and member functions,
> all one needs to "standardize" on are the capabilities that a container
> needs to have.

I suppose we could assign a number to each capability
and pretend that we weren't naming them. ;-)
But, yes, we need to "standardize" the capabilities.
We are giving them names so that we can identify them.
We are giving them standard names so that the application programmer
knows what to expect from the library.
We don't necessarily expect any of these names
to appear in application source code.

> The MatrixTraits class could be standardized,
> or every library could provide its own MatrixTraits type of class,
> specifying only those capabilities that that library needs,
> and leaving it up to the user of the library
> to specialize this class as is appropriate for his containers.
>
>> doubleComplexVector v(n);
>
> Ack! There is no good reason for not writing generic containers -
> this is generic programming at its most basic:
>
> Vector<complex<double>> v(n);

Obviously, templates could be used to implement doubleComplexVector
and the library developer could simply provide the type definition

typedef Vector<complex<double>> doubleComplexVector;

But I don't think I have any use for

Vector<complex<String>> v(n);

I don't even know if the imaginary part of a complex String has meaning
for anybody and, anyway, I don't want to specify a standard for it.

If you wish to propose a class template for Vector, please feel free to do so
but I think it has already been done. ;-)

Seriously now, the point is that I think we expect the library developer
to provide specializations for a certain limited number of types.
I don't think we expect library developers to provide any support
for types that hardly anyone ever uses.
It won't help them sell libraries and it isn't justified.
The decision about whether to use templates or not
is an implementation detail and should be left up to the library developer.
Bob Tisdale