Question sur la dactylographie

Ilya Malev  

Chers programmeurs, une question me taraude depuis longtemps. Est-il possible de faire en sorte que la valeur de retour d'une fonction soit implicitement typée ? Ainsi, une méthode d'une classe renverra une valeur d'un type différent, si l'appel des méthodes est identique en externe.

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

Il s'agit de la classe elle-même, vous n'avez pas besoin de la regarder, si la question est claire.

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  

Vous pouvez également vous débarrasser de swich lors de l'assignation et profiter des capacités de surcharge :

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

Ensuite, si la valeur de retour doit être utilisée pour une action arithmétique (afin qu'il y ait quelque chose à référencer), c'est à peu près la même chose :

   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");

---

Si c'est pour moi, je ferais des fonctions surchargées avec retour par paramètre par référence.

   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:

Vous pouvez également vous débarrasser de swich lors de l'assignation et profiter des capacités de surcharge :

Ensuite, si la valeur de retour est utilisée pour une action arithmétique (pour qu'il y ait quelque chose à chercher), c'est à peu près la même chose :

Avec la surcharge explicite et les actions arithmétiques, c'est clair comme de l'eau de roche. Oui, surchargé = clairement mieux dans ce cas, vous avez raison, j'étais juste en train de construire rapidement un exemple pour une question et je n'y ai pas vraiment pensé (bien qu'il n'y ait pas seulement int, mais aussi char, uchar, short, ushort, uint, bool et color, donc tout n'est pas simple )))))))).

Dmitry Fedoseev:

Si je devais faire des fonctions surchargées avec retour de paramètre par référence.


Le problème ici est que le type de la valeur de retourde la méthode surchargée dépend du contenu de l'objet.

Par exemple, nous avons un tableau multi-types (je ne citerai pas d'exemples, car il y a beaucoup de livres). Et bien sûr, tout tableau doit avoir l'opération d'indexation [] qui renvoie la valeur d'une variable avec un index approprié.

Mais les variables ont différents types. Cet index peut contenir une date, une chaîne ou tout autre type défini par l'utilisateur. Et idéalement, je voudrais que le type de valeur de retour produise automatiquement le type approprié lors de l'indexation de [], sans avoir à le paramétrer explicitement. J'avais l'habitude de résoudre ce "problème" de cette façon : var[(char)1], var[(short)1], var[(uint)1] etc., mais ces béquilles ne fonctionnent pas.

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;
 };
Ilya Malev  
une question similaire : pourquoi, lors de la surcharge d'une méthode (dans la signature de la méthode surchargée), le type de retour n'apparaît pas, seuls les types de paramètres apparaissent. c'est-à-dire que vous ne pouvez pas définir deux méthodes identiques avec des types de retour différents. pourquoi cette restriction ? quel est le but, pourquoi ne pouvez-vous pas surcharger une méthode par le type de retour de paramètres identiques ?
fxsaber  
Ilya Malev:

Dans ce cas, vous ne pouvez pas affecter p1 à p4 (avec un changement de type), ce qui devrait être possible en principe.

Ou dans le cas d'un tableau - des objets de différents types avec un seul type de base, mais l'objet tableau lui-même a une méthode, dont le type de retour dépend du type de l'objet avec l'index correspondant

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

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

Oui, pour transmettre 32 octets alors que dans 90% des cas 4 suffisent... De toute façon, ce n'est pas le but de ce fil de discussion, je suis intéressé par le but - peut-être quelqu'un a trouvé une solution plus ou moins gracieuse dans la situation décrite.


p.s. Par ailleurs, la question ne porte pas du tout sur le stockage de différents types de données dans un seul objet/structure.

fxsaber  
Ilya Malev:
une question similaire : pourquoi, lors de la surcharge d'une méthode (dans la signature de la méthode surchargée), le type de retour n'apparaît pas, seuls les types de paramètres apparaissent. c'est-à-dire que vous ne pouvez pas définir deux méthodes identiques avec des types de retour différents. pourquoi cette restriction ? quel est l'intérêt, pourquoi ne peut-on pas surcharger une méthode par type de retour avec des paramètres identiques ?

La méthode ne peut pas décider du type à retourner.

fxsaber  
Ilya Malev:

En d'autres termes, vous avez répété ce que j'ai écrit. La question n'est pas de savoir si elle le peut ou non, mais pourquoi elle ne le peut pas et comment la contourner avec élégance.

Le contrôle du type est perdu. Consultez les ressources C++ pour trouver des réponses à ces questions. Je pense qu'on les demande assez souvent.

Raison: