Bug del compilatore con il parametro template = void*

 

Errore del compilatore. Bild 1961, 64 bit.

template<typename T>
class A
{ 
};

A<void*> a;  // '<' - cannot to apply function
 
Era possibile prima?
 
Controllerò questo annuncio con C++ in serata
 
Vladimir Simakov:
Era possibile prima?

Sì. L'ho controllato specialmente sulla vecchia build (1554) - tutto funziona.

Lo controllerò stasera con tale annuncio in C++.

Beh, lì va sicuramente bene, c'è qualche motivo per cui non possa funzionare?
 
Alexey Navoykov:

Si prega di dare un esempio dell'uso di questa costruzione.

 
fxsaber:

Per favore, fate un esempio di come usare questo costrutto.

L'esempio più banale è una classe array, che in questo caso viene utilizzata per memorizzare qualsiasi puntatore:

template<typename T>
class CArray
{
  T _data[]; 
 public:
  T operator[](int i) const { return _data[i]; }
  int Size()          const { return ArraySize(_data); }
  // и т.д.
};

СArray<void*> pointers;
 
Alexey Navoykov:

L'esempio più banale è la classe array, che in questo caso viene utilizzata per memorizzare qualsiasi puntatore.

Come usarlo allora?

class A
{
public:
  void OnInit()
  {
    Print(__FUNCSIG__);
  }
};

class B
{
public:
  void OnInit()
  {
    Print(__FUNCSIG__);
  }
};

void OnStart()
{    
  void* Pointers[2];

  A a;
  B b;
  
  Pointers[0] = &a;
  Pointers[1] = &b;
  
  for (int i = 0; i < ArraySize(Pointers); i++)
    Pointers[i].OnInit(); // 'OnInit' - member function not defined
}
 
fxsaber:

Come usarlo allora?

Nello stesso modo in cui per esempio CObject è usato nei contenitori metaquote. Cast al tipo che hai messo lì inizialmente (o usa dynamic_cast per controllare). È un po' sorprendente sentirti fare questa domanda.
 
Alexey Navoykov:
Cast al tipo che ci avete messo originariamente (o controllare tramite dynamic_cast).
//    (A*)Pointers[i].OnInit();
    ((A*)Pointers[i]).OnInit();

Questo è solo sul tema se le parentesi sono necessarie/non necessarie... Con questo casting sarebbe una scocciatura nello script di cui sopra quando viene eseguito. Cioè dovete conoscere i nomi delle classi a cui si riferiscono gli elementi del puntatore dell'array.

Non vedo quale sia la convenienza allora.


MQ usa void* solo in un posto.

typedef string(*DoubleToStringFunction)(double,void*);
 
fxsaber:

MQ usa void* solo in un posto.

Poiché hanno tutto costruito su CObject, rende impossibile utilizzare i loro contenitori per le proprie classi e interfacce, non ereditate dalla loro classe. Cioè non è una soluzione universale.

Questo è probabilmente dovuto al fatto che al momento della creazione della loro libreria non c'era ancora void* in MQL. Ma d'altra parte il loro oggetto stesso partecipa anche ad alcune manipolazioni (cambiando i valori dei puntatori in esso), che di per sé è semplicemente selvaggio.

 
Alexey Navoykov:

Questo rende impossibile utilizzare i loro contenitori per le proprie classi e interfacce non ereditate dalla loro classe, cioè non è una soluzione universale.

Forse perché al momento della creazione della loro libreria, non c'era ancora void* in MQL.

Purtroppo non ho visto un esempio del suo utilizzo.