2

I have two longish blocks of code that are identical except in various comparative statements > is switched with <, >= with <= etc. I wanted to put these in a function and use one operator or another depending on a function input.

I am coding in MQL5 but this is very similar to C++ so hopefully methods that work in this will also be useable in my case.

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
whitebloodcell
  • 308
  • 1
  • 4
  • 10

3 Answers3

3

You can create a comparator function for each comparison you need, and then pass the right function as an argument to the longish code blocks (wrapped in a suitably defined function)

As an example, consider the following hypothetical case where a function (myFunc) receives 2 integers(a and b) and processes them. The processing steps are similar except for the type of comparison done on the arguments. We get around the problem by providing myFunc with the right tool for comparison.

#include <iostream>
using namespace std;

bool comp1(int a, int b) {
    return a > b;
}

bool comp2(int a, int b) {
    return a < b;
}

void myFunc(int a, int b, bool (*myComp)(int, int)) {
    bool res = myComp(a, b);
    cout << "value : " << res << endl;
}
int main()
{
    myFunc(1, 2, comp1); //use >
    myFunc(1, 2, comp2); //use <
    return 0;
}

Clearly, comp1 and comp2 are the 2 different comparators. We pass one of them to myFunc depending on the requirements (< or >).

The best thing is that your comparisons can now be as complex as you want, and myFunc is oblivious to the complexities.

axiom
  • 8,765
  • 3
  • 36
  • 38
  • Thank you, but unfortunately that doesn't seem to work in my environment. Do you know any other ways? – whitebloodcell Apr 26 '14 at 12:36
  • @whitebloodcell What are the restrictions that make this "not work" in your environment? – Casper Beyer Apr 26 '14 at 12:44
  • @whitebloodcell No idea about `mql5`, but one way of going about it might be to brainstorm and make sure that the ` longish blocks of code` are really necessary. Maybe you can restructure the code in a way that the operator dependent part is minimal. – axiom Apr 26 '14 at 12:45
  • 1
    By "not work" I just meant that the example you provided would not compile in my environment unfortunately. MQL5 is an object oriented language with syntax very similar to C++ (quoting from the creators). I can make use of encapsulation and extensibility of types, inheritance, polymorphism, overloading and virtual functions, pointers etc, but not your solution unfortunately. – whitebloodcell Apr 26 '14 at 13:31
  • It's valid C++ code but unfortunately MQL [doesn't support pointers to function](http://forum.mql4.com/4630) – manlio May 22 '14 at 17:04
2

Coding in MQL4 you haven't pointers to function / templates. MQL5 has templates but formal parameter types are only built-in or basic user-defined types.

You could try something like:

enum COMPARATOR
{
  C_EQUAL = 0,
  C_LESS = 1,
  C_GREATER = -1
  C_AT_MOST = 2,
  C_AT_LEAST = -2,
};

bool cmp(int a, int b, COMPARATOR c)
{
  switch (c)
  {
  case C_LESS:     return a < b;
  case C_AT_MOST:  return a <= b;
  case C_EQUAL:    return a == b;
  case C_AT_LEAST: return a >= b;
  case C_GREATER:  return a > b;
  }

  Alert("INTERNAL ERROR: UNKNOWN COMPARISON");
  return false;
}

void a_function(COMPARATOR c)
{
  if (cmp(MathRand(), 13, c))
    Print("BOOM");

  // *** If you need the "opposite" of c *** you can write:
  if (cmp(Time[0], Time[1], COMPARATOR(-c))
    Alert("DONE");
}

It isn't elegant but it's effective.

manlio
  • 18,345
  • 14
  • 76
  • 126
1

Pass in a "comparator" as a function or functor, in this case I'm using the std::less and std::greater functors defined in the functional header, there are functors defined for more or less all the operators.

#include <iostream>
#include <functional>

template<typename Comparator>
void do_something(Comparator comp)
{
   int a = 1;
   int b = 2;

   if (comp(a, b)) {
      std::cout << "expression was true" << std::endl;
   } else {
      std::cout << "expression was not true" << std::endl;
   }
}

int main(int argc, char* argv[])
{
   do_something(std::greater<int>());
   do_something(std::less<int>());
}

Output:

expression was not true
expression was true
Casper Beyer
  • 2,203
  • 2
  • 22
  • 35
  • In C++ this is a valid approach but unfortunately MQL5 doesn't support class templates / complex template formal parameters (i.e. functions / functors). – manlio May 22 '14 at 17:21