Domanda sulla digitazione

Ilya Malev  

Cari programmatori, è da molto tempo che mi tormenta una domanda. È possibile in qualche modo escogitare e rendere implicita la digitazione del valore di ritorno della funzione? In modo che un metodo di una classe restituisca un valore di un tipo diverso, se i metodi chiamati sono esternamente identici.

void OnStart()
 {
  CParameter p1 = Ask, p2 = Bid, p3 = TimeCurrent(), p4 = TimeLocal();
  
  // Перегруженный в CParameter оператор ~ возвращает преобразованное в строку значение известного объекту типа
  
  printf( "p1=%s, p2=%s, p3=%s, p4=%s", ~p1, ~p2, ~p3, ~p4 );
  
  // А можно ли исхитриться и сделать вот так (допустим это будет перегруженный тем или иным образом оператор !, возвращающий
  //   значение нужного типа в зависимости от type. 
  //
  // double ask = !p1, bid = !p2;
  // datetime current = !p3, local = !p4;  
 }  

Questa è la classe stessa, non c'è bisogno di guardarla, se la domanda è chiara.

enum TYPE{ NUMBER, PRICE, TIME };

class CParameter
 {
public:
  template<typename T> void operator= ( T par )
   {
    if( typename( T ) == "double" )
     {
      data = int( double( par ) * 100000 );
      type = PRICE;
     }
    else
     {
      if( typename( T ) == "datetime" )
       {
        data = int( uint( par ) );
        type = TIME;
       }
      else
       {
        data = int( par );
        type = NUMBER;
       }
     }
   }
   
  double to_price()
   {
    switch(type)
     {
      case PRICE: return double( data ) / 100000;
      case TIME:  return MathArcsin(2.0);
      default:    return double( data );
     }
   }

  datetime to_time()
   {
    switch(type)
     {
      case TIME:  return datetime( data );
      default:    return 0;
     }
   }

  int to_number()
   {
    switch(type)
     {
      case PRICE: return int( double( data ) / 100000 );
      case TIME:  return 0;
      default:    return data;
     }
   }
   
  string to_string()
   {
    switch(type)
     {
      case PRICE: return DoubleToString( to_price(), 5 );
      case TIME:  return TimeToString( to_time(), TIME_DATE|TIME_SECONDS );
      default:    return IntegerToString( data );
     }
   }
   
  string operator~ ()
   {
    return to_string();
   }
   
private:
  int data;
  TYPE type;
 };
Dmitry Fedoseev  

Potete anche sbarazzarvi dello swich quando assegnate e approfittare delle capacità di sovraccarico:

   void operator=(double par){
      data = int(double(par)*100000 );
      type = PRICE;
   }
   void operator=(datetime par){
      data=int(uint(par));
      type=TIME;
   }
   void operator=(int par){   
      data = int(par);
      type = NUMBER;
   }

Poi, se il valore di ritorno deve essere usato per un'azione aritmetica (in modo che ci sia qualcosa a cui fare riferimento), è circa lo stesso:

   string operator+(string par){
      return to_string()+par;
   }
   
   double operator+(double par){
      return to_price()+par;
   }   
   
   double operator+(int par){
      return to_number()+par;
   }  
Print(p1+1);
Print(p1+1.0);
Print(p1+"1");

---

Se per me stesso, farei funzioni sovraccaricate con ritorno tramite parametro per riferimento.

   void r(double & v){
      v=to_price();
   }
   void r(int & v){
      v=to_number();
   }   
   void r(string & v){
      v=to_string();
   }   
Ilya Malev  
Dmitry Fedoseev:

Potete anche sbarazzarvi dello swich quando assegnate e approfittare delle capacità di sovraccarico:

Poi, se il valore di ritorno sarà usato per un'azione aritmetica (in modo che ci sia qualcosa da cercare), è circa lo stesso:

Con l'overloading esplicito e le azioni aritmetiche, è chiaro come è. Sì, overloaded = chiaramente meglio in questo caso, hai ragione, stavo solo costruendo rapidamente un esempio per una domanda e non ci ho davvero pensato (anche se non ci sono solo int, ma anche char, uchar, short, ushort, uint, bool e colore, quindi non tutto è semplice )))))))).

Dmitry Fedoseev:

Se dovessi fare funzioni sovraccaricate con ritorno di parametri per riferimento.


Il problema qui è che il tipo del valore di ritornodel metodo sovraccaricato dipende dal contenuto dell'oggetto.

Per esempio, abbiamo un array multi-tipo (non citerò esempi, perché ci sono molti libri). E naturalmente, qualsiasi array deve avere l'operazione di indicizzazione [] che restituisce il valore di una variabile con un indice appropriato.

Ma le variabili hanno tipi diversi. Potrebbe esserci datetime o stringa o qualche altro tipo definito dall'utente sotto questo indice. E idealmente, vorrei che il tipo di valore di ritorno emettesse automaticamente il tipo appropriato quando si indicizza [], senza doverlo parametrizzare esplicitamente. Risolvevo questo "problema" in questo modo: var[(char)1], var[(short)1], var[(uint)1] ecc.

fxsaber  
void OnStart()
 {
  CParameter<double> p1 = Ask;
  CParameter<double> p2 = Bid;
  CParameter<datetime> p3 = TimeCurrent();
  CParameter<datetime> p4 = TimeLocal();
  
  // Перегруженный в CParameter оператор ~ возвращает преобразованное в строку значение известного объекту типа
  
  printf( "p1=%s, p2=%s, p3=%s, p4=%s", ~p1, ~p2, ~p3, ~p4 );
  
  // А можно ли исхитриться и сделать вот так (допустим это будет перегруженный тем или иным образом оператор !, возвращающий
  //   значение нужного типа в зависимости от type. 
  //
   double ask = !p1, bid = !p2;
   datetime current = !p3, local = !p4;  
 }  
template <typename T>
class CParameter
 {
public: 
  void operator =( const T Value )
  {
    this.data = Value;
  }

  string operator~( void) const
   {
    return((string)this.data);
   }
   
  T operator !( void ) const
  {
    return(this.data);
  }  
   
private:
  T data;
 };
fxsaber  
Ilya Malev:

In questo caso non potete assegnare p1 a p4 (con un cambio di tipo), cosa che dovrebbe essere possibile in linea di principio.

O in caso di array - oggetti di diversi tipi con un tipo base, ma l'oggetto array stesso ha un metodo, il cui tipo di ritorno dipende dal tipo di oggetto con indice corrispondente

https://www.mql5.com/ru/docs/constants/structures/mqlparam

Документация по MQL5: Константы, перечисления и структуры / Структуры данных / Структура входных параметров индикатора
Документация по MQL5: Константы, перечисления и структуры / Структуры данных / Структура входных параметров индикатора
  • www.mql5.com
каждого элемента этого массива указывает тип данных, передаваемых данным элементом. Сами значения параметров индикатора необходимо предварительно поместить в соответствующие поля каждого элемента (в...
Ilya Malev  

Sì, trasmettere 32 byte quando nel 90% dei casi 4 sono sufficienti... Comunque, non è questo il punto di questo thread, sono interessato allo scopo - forse qualcuno ha trovato una soluzione più o meno aggraziata nella situazione descritta


p.s. Inoltre, la domanda non riguarda la memorizzazione di diversi tipi di dati in un oggetto/struttura, affatto

fxsaber  
Ilya Malev:
una domanda simile: perché quando si sovraccarica un metodo (nella firma del metodo sovraccaricato) il tipo di ritorno non appare, ma solo i tipi di parametro. cioè non si possono definire due metodi identici con tipi di ritorno diversi. perché questa restrizione? qual è il punto, perché non si può sovraccaricare un metodo per tipo di ritorno con parametri identici

Il metodo non può decidere quale tipo restituire.

Ilya Malev  
fxsaber:

Un metodo non può decidere quale tipo restituire.

Beh, in altre parole hai ripetuto quello che ho scritto. La questione non era se può o non può, ma perché non può e come aggirare elegantemente il problema

fxsaber  
Ilya Malev:

Bene, in altre parole avete ripetuto quello che ho scritto. La questione non era se può o non può, ma perché non può e come aggirarlo con grazia.

Il controllo del tipo è perso. Cercate le risposte a queste domande nelle risorse C++. Penso che vengano chiesti abbastanza spesso.

Motivazione: