Typing question

 

Dear programmers, I've been puzzling over a question for a long time. Is it possible to somehow contrive and make implicit typing of function's return value? So that a method of a class will return a value of a different type, if calling the methods are externally identical.

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

This is the class itself, you don't have to look at it, if the question is clear.

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

You can also get rid of swich when assigning and take advantage of overloading capabilities:

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

Then, if the return value is to be used for an arithmetic action (so that there is something to reference), it's about the same:

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

---

If for myself, I would make overloaded functions with return via parameter by reference.

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

You can also get rid of swich when assigning and take advantage of overloading capabilities:

Then, if the return value will be used for an arithmetic action (so that there is something to look up), it's about the same:

With explicit overloading and arithmetic actions, it's clear as it is. Yes, overloaded = clearly better in this case, you're right, I just was quickly building an example for a question and not really thought about it (although there number not only int, but also char, uchar, short, ushort, uint, bool and color, so not everything is simple )))))))).

Dmitry Fedoseev:

If I were to make overloaded functions with parameter return by reference.


The issue here is that the type of theoverloaded method's return value depends on the object's content.

For instance, we have a multi-type array (I won't cite examples, since there are a lot of books). And of course, any array must have the [] indexing operation which returns the value of a variable with an appropriate index.

But variables have different types. There might be datetime or string or some other user-defined type under this index. And ideally, I would like the return value type to automatically output the appropriate type when indexing [], without having to explicitly parameterize it. I used to solve this "problem" this way: var[(char)1], var[(short)1], var[(uint)1] etc., but these crutches don't work.

 
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 this case, you can't assign p1 to p4 (with type change), and this should be possible in principle.

Or in case of array - objects of different types with one base type, but the array object itself has a method, which return type depends on object type with corresponding index
 
a similar question: why is it that when overloading a method (in the overloaded method signature) the return type does not appear, only the parameter types appear. i.e. you cannot define two identical methods with different return types. why this restriction? what is the point, why cannot you overload a method by the return type of identical parameters?
 
Ilya Malev:

In this case you can't assign p1 to p4 (with a type change), which should be possible in principle.

Or in case of array - objects of different types with one base type, but the array object itself has a method, which return type depends on the type of object with corresponding index

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

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

Yes, to transmit 32 bytes when in 90% of cases 4 is enough... Anyway, that's not the point of this thread, I'm interested with the purpose - may be someone found more or less graceful solution in described situation


p.s. Besides, the question is not about storing different types of data in one object/structure, at all

 
Ilya Malev:
a similar question: why when overloading a method (in the overloaded method signature) the return type does not appear, only the parameter types appear. i.e. you cannot define two identical methods with different return types. why is this restriction made? what is the point, why cannot overload a method by return type with identical parameters

The method cannot decide what type to return.

 
fxsaber:

A method cannot decide what type to return.

Well, in other words you repeated what I wrote. The question was not whether it can or cannot, but why it cannot and how to elegantly work around it

 
Ilya Malev:

Well, in other words you have repeated what I wrote. The question was not whether it can or cannot, but why it cannot and how to get around it gracefully.

Type control is lost. Look through the C++ resources for answers to these questions. I think they are asked quite often.

Reason: