0

Can someone tell me if this is correct. I'm trying to overload my << operator for an array in my dynamic array class below.

Specefically,

Can I put std:ostream in the class itself? This does not seem corrrect. Compiler error is telling me it should only take one argument.

void print_array(std::ostream &os = cout) 
  { 
  for (int i = 0; i < size; i++) os << array[i] << endl; 
  } 
    std::ostream& operator<<(std::ostream& stream, dynamic_array const& data) 
  { 
  data.print_array(stream);
  return stream; 
  }

Dynamic Array Class

/*
Needs a reszie function added
Merge sort is better for sequential, stable(equal elements not re-arranged, or
*/
#include "c_arclib.cpp"

template <class T> class dynamic_array
  {
  private:
    T* array;
    T* scratch;
    void merge_recurse(int left, int right)
      {
      if(right == left + 1)
        {
        return;
        }
      else
        {
        int i = 0;
        int length = right - left;
        int midpoint_distance = length/2;
        int l = left, r = left + midpoint_distance;
        merge_recurse(left, left + midpoint_distance);
        merge_recurse(left + midpoint_distance, right);
        for(i = 0; i < length; i++)
          {
          if((l < (left + midpoint_distance)) && (r == right || array[l] > array[r]))
            {
            scratch[i] = array[l];
            l++;
            }
          else
            {
            scratch[i] = array[r];
            r++;
            }
          }
        for(i = left; i < right; i++)
          {
          array[i] = scratch[i - left];
          }
        }
      }
    void quick_recurse(int left, int right) 
      {  
      int l = left, r = right, tmp;
      int pivot = array[(left + right) / 2];
      while (l <= r)
        {
        while (array[l] < pivot)l++;
        while (array[r] > pivot)r--;
        if (l <= r) 
          {
          tmp = array[l];
          array[l] = array[r];
          array[r] = tmp;
          l++;
          r--;
          }
        }
      if (left < r)quick_recurse(left, r);
      if (l < right)quick_recurse(l, right);
      }  
  public:
    int size;
    dynamic_array(int sizein)
      {
      size=sizein;
      array = new T[size]();
      }
    void print_array(std::ostream &os = cout) 
      { 
      for (int i = 0; i < size; i++) os << array[i] << endl; 
      } 
    std::ostream& operator<<(std::ostream& stream, dynamic_array const& data) 
      { 
      data.print_array(stream);
      return stream; 
      }
    void print_array()
      {
      for (int i = 0; i < size; i++) cout << array[i] << endl;
      }
    int merge_sort()
      {
      scratch = new T[size]();
      if(scratch != NULL)
        {
        merge_recurse(0, size);
        return 1;
        }
      else
        {
        return 0;
        }
      }
    void quick_sort()
      {
      quick_recurse(0,size);
      }
    void rand_to_array()
      {
      srand(time(NULL));
      int* k;
      for (k = array; k != array + size; ++k)                                             
        { 
        *k=rand();                                      
        } 
      }
    void order_to_array()
      {
      int* k;
      int i = 0;
      for (k = array; k != array + size; ++k)                                             
        { 
        *k=i;
        ++i;        
        } 
      }
    void rorder_to_array()
      {
      int* k;
      int i = size;
      for (k = array; k != array + size; ++k)                                             
        { 
        *k=i;
        --i;        
        } 
      }
  };
int main()
  {
  dynamic_array<int> d1(1000000);
  d1.order_to_array();
  clock_t time_start=clock();
  d1.merge_sort(); 
  clock_t time_end=clock();
  double result = (double)(time_end - time_start) / CLOCKS_PER_SEC; 
  cout << result;
  }
  • http://stackoverflow.com/questions/7975999/operator-overload-for-dynamic-array-giving-strange-error –  Nov 02 '11 at 05:04

2 Answers2

1

Put the operator outside of your class:

template <class T> class dynamic_array
{
    ...
    // if you need to use protected/private members:
    friend std::ostream& operator<<(std::ostream& stream,
                                    dynamic_array<T> const& data);
}
template <class T>
std::ostream& operator<<(std::ostream& stream, dynamic_array<T> const& data) 
{ 
    data.print_array(stream);
    return stream; 
}
Daniel
  • 30,896
  • 18
  • 85
  • 139
  • compiler error is telling me dynamic_array is not a type...but it is clealy defined as you show above??? –  Nov 02 '11 at 04:19
  • @ChrisAaker: forgot you need to repeat the template – Daniel Nov 02 '11 at 04:22
  • it works not...I don't know why I wrote this monstrosity...except someone in code review told me it is a good idea...is it...the syntax makes me suicidal...I'm not so sure –  Nov 02 '11 at 04:25
  • @ChrisAaker: templates are scary at first, but they are beautiful if you learn to use them correctly. – Daniel Nov 02 '11 at 04:27
  • will it works as a friend...other SO is telling me it should b global –  Nov 02 '11 at 04:29
  • @ChrisAaker: its global and friend in my example – Daniel Nov 02 '11 at 04:30
  • @Chris it should work without needing to friend it. `operator <<` uses your `dynamic_array::print_array` which is public. You'll want to make print_array a const method though. – greatwolf Nov 02 '11 at 04:41
  • no debugger.....reposted here....http://stackoverflow.com/questions/7975999/operator-overload-for-dynamic-array-giving-strange-error –  Nov 02 '11 at 05:07
  • i should probably set up code blocks...I started with Min...moved to a Boost Implementation...and I guess now I shoudld add a debugger. –  Nov 02 '11 at 05:11
1

Since the left operand of the operator<< will be the ostream, not the dynamic array object, you need to implement operator<< as a global function, not a member function (a member function overload is always invoked as object.operator<<(argument), so the object of which it's a member must be the left operand.

If that needs access to the internals of the object, you can make it a friend. If (as in this case) it uses only the public interface of the object (print_array, in your case), then it can just be a normal global function.

template <class T>
class dynamic_array {
    // ...
};

template <class T>
std::ostream &operator<<(std::ostream &os, dynamic_array<T> const &a) { 
    a.print_array(os);
    return os;
}

Personally, however, I'd probably make print_array a private member, and make the global operator<< a friend. This reduces the public interface of the class a bit (i.e., only one way to print a dynamic_array instead of two) with no loss of functionality (since the do precisely the same thing).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111