From: jdart@igor.rational.COM (Jon Dart)
Subject: template bug in gcc 2.3.1 (core dump)
Organization: Gnus Not Usenet
Distribution: gnu
Date: Thu, 12 Nov 1992 19:07:15 GMT

The following code core-dumps g++ version 2.3.1, running on a SPARCstation 2
under Sun OS 4.1.1.  I believe the code is correct and should compile.
The messages output are:

array.hh: In function `int  main (int, char **)':
array.hh:56: inconsistent return types for method `Array' in class `Array<int ,i
nt>'
array.hh:56: inconsistent return types for method `Array' in class `Array<int ,i
nt>'
/usr/local/bin/gcc: Internal compiler error: program cc1plus got fatal signal 11


Apparently it does not recognize the constructor as a constructor.

------------ code follows -------------
#ifndef _SUPPORT_BOOLEAN_H
#define _SUPPORT_BOOLEAN_H

class Boolean
{
 public:
  inline Boolean ();
  // default constructor (result is False)
   
  inline Boolean (const long);
  inline operator long () const;
  // Convert between Boolean and long

 private:
   long Bit;
};

extern const Boolean& True;
extern const Boolean& False;

inline Boolean::Boolean ()
  : Bit (0)
{}

inline Boolean::Boolean (const long That)
  : Bit (That != 0)
{}

inline Boolean::operator long () const 
{
    return Bit; 
}

#endif

#include <stddef.h>
#include <assert.h>
#include "boolean.hh"

template <class Contents, class Index >
class Array 
{
public:
      // Defines a simple, resizable-length array.  Copy and
      // assignment operators create duplicate copies of array
      // elements; i.e. there is no data-sharing across array
      // instances.

  Array( const Index initial_size );

  virtual ~Array();
  Array( const Array & );
  Array & operator = (const Array & );

  Boolean      operator == (const Array &) const;
  Boolean      operator != (const Array &) const;
      // These functions assume that Contents has a meaningful ==
      // operator

  virtual Contents &operator [] (const Index &) const;
      // Note: we return a reference so that Array[k] = stuff works.
      // An out-of-range index calls constraint_error, below

  int size() const
  {
    return data_size;
  }

  virtual void resize( const Index new_size );
      // The default behavior is to allocate a new array each
      // time this is called.  This is not suitable if one wants
      // to frequently expand the array by small increments.
      // That's why it's virtual: so you can do something different.

  Array &operator += (const Contents &Data );
  Array &operator += (const Array &Data );

  friend Array operator + (const Array&, const Contents &);
  friend Array operator + (const Contents &, const Array&);
  friend Array operator + (const Array&, const Array&);

  virtual void constraint_error(const Index index, const Index size);
      // Called when an index exceeds the bounds of the array.
      // The base version causes an assertion failure (may be
      // disabled by compiling with -DNDEBUG).

protected:
  Contents *data;
  Index data_size;
};

template <class Contents, class Index>
Array<Contents,Index>::Array( const Index initial_size )
{
  data_size = initial_size;
  data = new Contents [initial_size];
}

template <class Contents, class Index>
Array<Contents,Index>::~Array()
{
  delete [] data;
}

template <class Contents, class Index>
Array<Contents,Index>::Array( const Array<Contents,Index> &arr)
{
    data_size = arr.data_size;
    data = new Contents [arr.length()];
    for (Index i = 0; i < data_size; i++)
      data[i] = arr.data[i];
}

template <class Contents, class Index>
Array <Contents,Index>& Array<Contents,Index>::operator = (const Array<Contents,Index> &arr)
{
  if (this != &arr)
  {
    data_size = arr.data_size;
    data = new Contents [arr.length()];
    for (Index i = 0; i < data_size; i++)
      data[i] = arr.data[i];
  }
  return *this;
}

template <class Contents, class Index>
Boolean Array<Contents,Index>::operator == (const Array<Contents,Index> & arr) const
{
  if (arr.data_size != data_size)
    return False;
  for (Index i = 0; i<data_size;i++)
    if (arr.data[i] != data[i])
      return False;
  return True;
}

template <class Contents, class Index>
Boolean Array<Contents,Index>::operator != (const Array<Contents,Index> & arr) const
{
  if (arr.data_size != data_size)
    return True;
  for (Index i = 0; i<data_size;i++)
    if (arr.data[i] != data[i])
      return True;
  return False;
}

template <class Contents, class Index>
Contents& Array<Contents,Index>::operator [](const Index &index) const
{
#ifndef NDEBUG
   if (index < 0 || index >= data_size)
   {
      constraint_error(index,data_size);      
   }
#endif
   return data[index];
}

template <class Contents, class Index>
Array<Contents,Index> &Array<Contents,Index>::operator += (const Contents &Data )
{
   // not very efficient
   Index old_data_size = data_size;
   resize(data_size + 1);
   data[old_size] = Data;
   return *this;
}

template <class Contents, class Index>
Array<Contents,Index> &Array<Contents,Index>::operator += (const Array <Contents,Index>&Data )
{
   Index old_size = data_size;
   resize(data_size + Data.size);
   for (Index i = old_size; i < data_size; i++)
     data[i] = Data.data[i-old_size];
   return *this;
}

template <class Contents, class Index>
void Array<Contents,Index>::resize( const Index new_size )
{
   Contents * new_data = new Contents[new_size];
   assert(new_data);
   for (Index i = 0; i<data_size; i++)
      new_data[i] = data[i];
   delete [] data;
   data = new_data; 
   data_size = new_size;
}

template <class Contents, class Index>
Array<Contents,Index> operator + (const Array<Contents,Index>& arr, const Contents &c)
{
   Array<Contents,Index> ret_val(arr.length() + 1);
   for (Index i=0;i<arr.length();i++)
      ret_val.data[i] = arr.data[i];
   ret_val.data[arr.length()] = c;
   return ret_val;
}

template <class Contents, class Index>
Array<Contents,Index> operator + (const Contents &c, const Array<Contents,Index>&arr)
{
   Array<Contents,Index> ret_val(arr.length() + 1);
   for (Index i=0;i<arr.length();i++)
      ret_val.data[i] = arr.data[i];
   ret_val.data[arr.length()] = c;
   return ret_val;
}

template <class Contents, class Index>
Array<Contents,Index> operator + (const Array<Contents,Index>&arr1, 
			    const Array<Contents,Index>&arr2)
{
   Array<Contents,Index> ret_val(arr1.length() + arr2.length());
   for (Index i=0;i<arr1.length();i++)
      ret_val.data[i] = arr2.data[i];
   const Index start = arr1.length();
   for (i=start;i<start + arr2.length();i++)
      ret_val.data[i] = arr2.data[i-start];
   return ret_val;
}

template <class Contents, class Index>
void Array<Contents,Index>::constraint_error(const Index index,
				       const Index limit)
{
  assert(index >= 0 && index < limit);
}

#include "array.hh"
#include <iostream.h>

main(int argc, char**argv)
{
  Array<int,int> stuff( 10 );
  for (int i=0;i<stuff.size();i++)
  {
    stuff[i] = i*i - 8*i + 5;
    cout << "stuff[" << i << "] = " << stuff[i] << endl;
  }
}