[comp.lang.c++] Programming Challenge

harold@fmrco (Harold Naparst) (12/15/90)

I am trying to write a function which will return the index
of the smallest element of an array.  I want the routine
to work for any type array.  That is, I don't want to write
a separate routine for each type of array (real or double or
integer).  How can I do this ?  I tried playing around with 
the GNU C typeof operator, but couldn't figure it out.  Any ideas ?

Harold Naparst
(uunet!fmrco!harold)
-- 
Harold Naparst                  (uunet!fmrco!harold) 
Fidelity Management Trust Co.   (617)-570-2587
82 Devonshire St., #I40F        The opinions expressed herein are not those
Boston, MA  02109               of my employer.

maguire@sun.soe.clarkson.edu (Bill Maguire) (12/18/90)

In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:

>I am trying to write a function which will return the index
>of the smallest element of an array.  I want the routine
>to work for any type array.  That is, I don't want to write
>a separate routine for each type of array (real or double or
>integer).  How can I do this ?  I tried playing around with 
>the GNU C typeof operator, but couldn't figure it out.  Any ideas ?

>Harold Naparst

Tw ways immediately pop to mind:

1) overload the function to take a real*, double* or integer*.  You'll
have to do some text editing to copy the code and replace the types
but this is where templates come in.  With templates you can write
only one of the functions and the compiler will generate the
completed function definitions as you use them.

(This isn't entirely true in GNU g++ yet, there is a SED script, I 
believe, that given a template will generate the function definitions
that you ask of it)

2) The problem with having the same "compiled code" work on an array
of real, double, or integer is that these objects are in no way
related through any hierarchy.  So any call to the function cannot
be resolved polymorphically at run time.  To correct this create a 
hierarchy of Numbers with Number as an abstract base class.  You will 
have to do a lot of work defining the operators between numbers as it 
will take two virtual calls to resolve the type of each operand.
   At this point you can create an Array of Number object.  Now write
the function to work on an Array of Number.  This will be slower than
the first example as a great deal of polymorphic calls will have to be
made, but less compiled code will be generated.  (Not really, as you 
have to add the code for your whole type hierarchy) Another "problem" 
with this solution is that the Arrays are no longer limited to one type,
you could have Integers, Reals, and Doubles in the same list.  Not
quite what you want.
   However you could do some more work and define the classes 
Array of Integer, Array of Real, and Array of Double as subclasses of
Array of Number.  These class would have to know what to do if they 
were asked to set an element to the wrong type (i.e error), 
(Actually if you were using an overload operator[] and passing back
a reference as an lvalue than this can be resolved in the Number class)
but they could be implemented much more efficiently than a straight array 
of number.
   Now you have what you want.  A lot of work though.

Bill Maguire
sun.soe.clarkson.edu  
She had so many chins, she looked like a piece of lisp code :-))))))

noren@dinl.uucp (Charles Noren) (12/19/90)

In article <MAGUIRE.90Dec17132020@sun.clarkson.edu> maguire@sun.soe.clarkson.edu (Bill Maguire) writes:
 >In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:
 >
 >>I am trying to write a function which will return the index
 >>of the smallest element of an array.  I want the routine
 >>to work for any type array.  That is, I don't want to write
 >>a separate routine for each type of array (real or double or
 >>integer).  How can I do this ?  I tried playing around with 
 >>the GNU C typeof operator, but couldn't figure it out.  Any ideas ?
 >
 >>Harold Naparst
 >
 >Two ways immediately pop to mind:

...or you could wait until AT&T implements Parameterized Types,
or use (AT YOUR OWN RISK) one of the C++ compilers that has a version
Parameterized Types (e.g., the C++ that comes with ObjectStore OODBMS
by Object Design, Inc).


-- 
Chuck Noren
NET:     dinl!noren@ncar.ucar.edu
US-MAIL: Martin Marietta I&CS, MS XL8058, P.O. Box 1260,
         Denver, CO 80201-1260
Phone:   (303) 971-7930

scs@adam.mit.edu (Steve Summit) (12/19/90)

In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:
>I am trying to write a function which will return the index
>of the smallest element of an array.  I want the routine
>to work for any type array.

[Someone may well already have suggested this; I might have
missed it because my news feed appears to be flakey.]

Since the question was crossposted to comp.lang.c, here's the
straight-C answer, which doesn't involve any mucking about with
derived or generic types.  The caller does, on the other hand,
have to provide a comparison routine appropriate for the data
type being searched.  (Come to think of it, this probably isn't
what Mr. Naparst was looking for at all.  Oh, well, the technique
is instructive, and understanding it helps avoid problems when
using qsort and bsearch.)

Given

	sometype array[SOMESIZE];

and

	int sometypecmp(void *p1, void *p2)
	{
	sometype *sp1 = (sometype *)p1;
	sometype *sp2 = (sometype *)p2;

	if(*sp1 < *sp2)
		return -1;
	else if(*sp1 == *sp2)
		return 0;
	else	return 1;
	}

(this could return *sp1 - *sp2 if overflow wasn't a problem, and
might have to use more complicated relationals for nonarithmetic
types),

we can call

	findbiggest(array, SOMESIZE, sizeof(sometype), sometypecmp);

where findbiggest is

	findbiggest(void *a, size_t n, size_t elsize, int (*cmp)(void*,void*))
	{
	void *biggest = a;
	register int i;
	char *p2;		/* not void * so can do pointer arithmetic */

	for(i = 1, p2 = (char *)a + elsize; i < n; i++, p2 += elsize)
		{
		if((*cmp)(p2, biggest) > 0)
			biggest = p2;
		}

	return ((char *)biggest - (char *)a) / elsize;
	}

(Actually, a more likely implementation, closer to bsearch, would
return a pointer to the largest element, not the index.)

                                            Steve Summit
                                            scs@adam.mit.edu

platt@ndla.UUCP (Daniel E. Platt) (12/21/90)

In article <1990Dec15.015355.15683@fmrco>, harold@fmrco (Harold Naparst) writes:
> 
> I am trying to write a function which will return the index
> of the smallest element of an array.  I want the routine
> to work for any type array.  That is, I don't want to write
> a separate routine for each type of array (real or double or
> integer).  How can I do this ?  I tried playing around with 
> the GNU C typeof operator, but couldn't figure it out.  Any ideas ?
> 

Hi,

I think that you'd need to provide some sort of comparator function that
will actually do the comparison between the various elements, and all you
need to be able to do is pass the size of the data objects so that you can
compute the comparison pointers.  Example:

int least_find(base, nel, size, compar)
char *base;
int nel, size;
int (*compar)();
{
	int i, i_least;

	for (i = i_least = 0; i < nel; i++)
		if ((*compar)(base + i * size, base + i_least * size) < 0)
			i_least = i;

	return i_least;
}

Then, all you'd need to do is pass the function in compar that would handle
the comparison between your two types, and which would yield a value > 0, = 0,
or < 0 depending on which element was larger.

/* a function that will compare two integers */
int comp(u, v)
int *u, *v;
{
	return (*v - *u);
}

/*
** a section of code that will find the smallest out of N elements of array
** ar[] of ints using comp().
*/

	least = least_find(ar, N, sizeof(int), comp);

Hope this gives you more of a feel of how this has been handled in the
past...

Dan

rfg@NCD.COM (Ron Guilmette) (12/22/90)

In article <1990Dec15.015355.15683@fmrco> harold@fmrco (Harold Naparst) writes:
>
>I am trying to write a function which will return the index
>of the smallest element of an array.  I want the routine
>to work for any type array.  That is, I don't want to write
>a separate routine for each type of array (real or double or
>integer).  How can I do this ?  I tried playing around with 
>the GNU C typeof operator, but couldn't figure it out.  Any ideas ?



I see that there have been a few responses to this already, but I didn't
see anyone actually give what I consider to be a `good' answer.

The question was how to "write" a generic function to find the index of
the smallest element of an array of an arbitrary type.  The questioner
did not say anything about actually needing to compile it into executable
code with the help of any currently available C++ language processor.
:-) :-) :-)

Here is a solution:


template<class T> unsigned smallest (T array[], unsigned array_size)
    throw (Range_Error)
{
  T* smallest_value_p = &array[0];
  unsigned smallest_index = 0;

  if (array_size == 0)
    throw Range_Error (Zero_Length);

  for (unsigned i = 1; i < array_size; i++)
    if (array[i] < *smallest_value_p)
      {
	smallest_value = &array[i];
	smallest_index = i;
      }

  return i;
}

Won't life be beautiful when we can actually *use* templates & exceptions?

-- 

// Ron Guilmette  -  C++ Entomologist
// Internet: rfg@ncd.com      uucp: ...uunet!lupine!rfg
// Motto:  If it sticks, force it.  If it breaks, it needed replacing anyway.