How to use class forward declaration? - page 2

 
Stanislav Korotky:

Can you post actual codes to check?

I am using the OP's code, above, plus trivial tests of the class instantiation such as my messages a few minutes ago.

While there are ways of working round the problem, I agree with the OP that his code should compile successfully, but does not.

 
Stanislav Korotky:

Can you post actual codes to check?

As for "default constructor" error, you should either define it in order to declare array of objects m_rows[], or change its type to array of pointers and create/copy instances as appropriate.


Sorry about the confusion, here are the updated codes with the forward declaration.  I got compiler error:

'm_rows' - default constructor of class 'C1dArray<int>' is not defined  2darray q on forward declaration.mqh    17      15
 
williamwong:

Sorry about the confusion, here are the updated codes with the forward declaration.  I got compiler error:


This was interesting so I reduced it down to a simple test case

template<typename T> class Bar;

template<typename T> class Foo
{
public:
   Foo() {}
   void Test(const Bar<T>&);
};

template<typename T> class Bar
{
   Foo<T> aFoo;
   Foo<T> arrayFoo[];
};

int start()
{
   Foo<int> f;
   
   return 0;
}

'Foo<int>' - struct undefined                                                            (line 12)
'arrayFoo' - default constructor of class 'Foo<int>' is not defined       (line 13)

 

Could you use a jagged object array to achieve your desired result?

 
nicholishen:

Could you use a jagged object array to achieve your desired result?

Jagged Arrays

A variation of the multidimensional array is the jagged array: an array of arrays. A jagged array is a single-dimensional array, and each element is itself an array. The element arrays are not required to all be of the same size.

This is what I searched and found the definition of jagged array.  In fact, I am implementing a jagged array.  To make the code more readable, I removed all the other methods.

I got the following compilation errors:

'm_rows' - default constructor of class 'C1dArray<int>' is not defined mt Test forward declaration.mq4 29 15
object of 'C2dArray<int>' cannot be returned, copy constructor 'C2dArray<int>::C2dArray<int>(const C2dArray<int> &)' not found mt Test forward declaration.mq4 20 54

Anyway, I have reported this as a bug via the service desk and it has been accepted as open issue since 10 Oct.

template<typename T> class C2dArray;
//+------------------------------------------------------------------+
//| 1d array containing type T
//+------------------------------------------------------------------+
template<typename T>
class C1dArray
  {
private:
   T                 m_array[];
public:
                     // default constructor for C1dArray<int> should be defined here
                     C1dArray() {}
   // this method creates compilation problem, I wanted to pass in 2d array as
   // index (hence int type) to the 1d array elements
   C2dArray<T>operator[](C2dArray<int>&index) { return NULL; }
  };
//+------------------------------------------------------------------+
//| arrays of 1d array containing type T
//+------------------------------------------------------------------+
template<typename T>
class C2dArray
  {
private:
   C1dArray<T>m_rows[];
public:
                     C2dArray(C2dArray &a) { }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void start() 
  {
   C1dArray<int>try();
  }
 

Not sure if it helps but here is how you can create jagged arrays with the std lib classes. 

#include <Arrays\ArrayObj.mqh>
#include <Arrays\ArrayInt.mqh>
//+------------------------------------------------------------------+
class IntMatrix : public CArrayObj
{  
   public:CArrayInt* operator[](const int index)
   {
      if(index < Total())  
         return At(index); 
      CArrayInt *ptr = NULL;
      while(index >= Total())
      {
         ptr = new CArrayInt();
         Add(ptr);
      }
      return ptr;
   }
};

void OnStart()
  {
//---

   int cnt=0;
   IntMatrix matrix;
   for(int i=0;i<5;i++)
      for(int j=0;j<5;j++)
         matrix[i].Add(cnt++);
   
   for(int i=0;i< matrix.Total();i++)
      for(int j=0;j<matrix[i].Total();j++)
         Print(matrix[i][j]);
   
  }
 

And if you're just using std data types and you need a dynamic matrix then this should do the trick. 

Files:
 
nicholishen:

And if you're just using std data types and you need a dynamic matrix then this should do the trick. 


Thanks, for your suggestion.  I was fine using either way until I encountered the following requirement to pass a 2d array into 1darray as index:

C1darray y = {0,100,200,300,400,500,600,700,800,900}; // some data labels
C2darray pred_y = 
{{1,0,2},
{2,7,6},
{5,8,1}};

y[pred_y] will return 
{{100,0,200},
{200,700,600},
{500,800,100}}

This kind of indexing is very common in machine learning and python supports it natively.  I am converting some python codes into MQL and trying to write nd arrays to support this kind of fanciful indexing which saves a lot of coding.

C2dArray stores C1dArray in m_rows.  C1dArray operator[] needs to take in C2dArray as parameter.  This requires a forward declaration for C2dArray before defining C1dArray.  The sample code should compile but failed.  I have changed to dynamic version per your suggestion:

#include <Arrays\ArrayObj.mqh>
template<typename T> class C2dArray;
//+------------------------------------------------------------------+
//| 1d array containing type T
//+------------------------------------------------------------------+
template<typename T>
class TemplateData : public CObject
{
protected:
   T           m_data;
};

template<typename T>
class C1dArray:public CArrayObj
  {
public:
   // this method creates compilation problem, I wanted to pass in 2d array as
   // index to the 1d array elements
   C2dArray<T>operator[](C2dArray<int>&index) { return NULL; }
  };
//+------------------------------------------------------------------+
//| arrays of 1d array containing type T
//+------------------------------------------------------------------+
template<typename T>
class C2dArray:public CObject
  {
   CArrayObj m_rows;
public:
                     C2dArray(C2dArray &a) { }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void start() 
  {
   C1dArray<int>try();
  }

Still the same error:

object of 'C2dArray<int>' cannot be returned, copy constructor 'C2dArray<int>::C2dArray<int>(const C2dArray<int> &)' not found mt Test forward declaration.mq4 24 56

 
williamwong:

object of 'C2dArray<int>' cannot be returned, copy constructor 'C2dArray<int>::C2dArray<int>(const C2dArray<int> &)' not found mt Test forward declaration.mq4 24 56

   C2dArray<T>* operator[](C2dArray<int>&index) { return NULL; }