Domanda sulla digitazione

 

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;
 };
 

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();
   }   
 
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.

 
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:

In questo caso, non puoi assegnare p1 a p4 (con cambio di tipo), e questo 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
 
una domanda simile: perché quando si sovraccarica un metodo (nella firma del metodo sovraccaricato) il tipo di ritorno non appare, solo i tipi di parametro appaiono. 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 dal tipo di ritorno di parametri identici?
 
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
каждого элемента этого массива указывает тип данных, передаваемых данным элементом. Сами значения параметров индикатора необходимо предварительно поместить в соответствующие поля каждого элемента (в...
 

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

 
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.

 
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

 
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: