如何定义指向同名静态类方法的全局宏?

时间:2017-01-17 14:10:55

标签: compiler-errors syntax-error mql4 mql5

我有以下MQL4 / 5代码:

class MQL4 {
public:
  static double Ask() {
    MqlTick _tick;
    SymbolInfoTick(_Symbol, _tick);
    return _tick.ask;
    // Overriding Ask variable to become a function call.
    #define Ask MQL4::Ask()
  }

};

void start() {
  double ask = Ask; // line 14
};

然而,根据错误,它无法在MQL4或MQL5下编译:

> mql /s /mql5 Test.mqh
MQL4/MQL5 Compiler build 1162 (02 Jul 2015)
Test.mqh : information: Checking 'Test.mqh'
Test.mqh(14,16) : error 320: 'Ask' - too complex, simplify the macro
Test.mqh(14,16) : error 239: '::' - syntax error
Test.mqh(14,16) : error 239: '::' - syntax error
Test.mqh(14,16) : error 239: '::' - syntax error
Test.mqh(14,16) : error 239: '::' - syntax error
Test.mqh(14,16) : error 239: '::' - syntax error
Test.mqh(14,16) : error 239: '::' - syntax error
Test.mqh(14,16) : error 239: '::' - syntax error
Test.mqh(14,16) : error 149: unexpected token
Test.mqh(14,16) : error 149: ')' - unexpected token
Test.mqh(14,16) : error 157: 'MQL4' - expression expected
Test.mqh(14,10) : warning 31: variable 'ask' not used
 : information: Result 11 error(s), 1 warning(s)

与最新的1498版本相同的错误。

基本上它说Ask太复杂的宏。虽然将 Ask() 方法重命名为 GetAsk() 并更新宏定义时效果正常但是我是如果有任何其他解决方案而不必重命名,我想了解。

是否有任何语法可以定义macro substitution,可以理解以下宏:

#define Ask MQL4::Ask()

而不必在保持静态类方法的同时重命名它?

2 个答案:

答案 0 :(得分:1)

是的,但是......,不!!#define替换工作正常,但是......
Ask 是保留字,这会混淆编译器。

问题实际上是编译器预处理器的功能有限,而不是 .method() 的“同名”。

#define 指令,非参数和参数替换功能都经过测试,符合已发布的MQL4 / 5语言语法的限制。

Case[6]终于证明了,

Class.<_method_>() 可以使用相同名称 .Ask() ,但不能与 #define相同 -s <_literal_symbol_to_substitute_>

//+------------------------------------------------------------------+
//|                                   StackOverflow__test_DEFINE.mq4 |
//|                                       Copyright © 1987-2017 [ME] |
//|                                                       nowhere.no |
//+------------------------------------------------------------------+
#property strict
 // -------------------------------------------------------------------------------------------------------------------------
/*                                                       // [Case[1] FAILS BELOW
#define               Ask MQL4::Ask( True )              // [Case[1] // Overriding Ask variable to become a function call. */

class MQL4 { 
     public:
     static double Ask( bool FakeSyntaxSUGAR = False ) { // [Case[1] FAILS HERE TO PROCESS EXPANDED PRE-PROCESSOR #define SUBSTITUTION]
                        MqlTick _tick;
                        SymbolInfoTick( _Symbol,
                                        _tick
                                        );
                        return _tick.ask;
         }
};

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+

void OnStart() {

 // -------------------------------------------------------------------------------------------------------------------------
/*                                                       // [Case[2] FAILS
#define               Ask MQL4::Ask( True )              // [Case[2] // Overriding Ask variable to become a function call. */
  // double ask     = Ask;                               // [Case[2] FAILS TO COMPILE, ERROR on "Ask;"]


  // ------------------------------------------------------------------------------------------------------------------------
  // double askMQL4 = MQL4::Ask( True );                 // [Case[3] OK    TO COMPILE EXPLICIT CALL TO an explicit absolute reference to a method-name]


 // -------------------------------------------------------------------------------------------------------------------------
/*                                                       // [Case[4] OK */
     MQL4* aPtrToINSTANCE = new MQL4();                  // [Case[4]
  // double askINST = aPtrToINSTANCE.Ask( False );       // [Case[4] OK    TO COMPILE EXPLICIT CALL TO aPtrToINSTANCE-referred instance of Class ]

 // -------------------------------------------------------------------------------------------------------------------------
/*                                                       // [Case[5] FAILS
#define               Ask aPtrToINSTANCE.Ask( False )    // [Case[5] */
  // double askINST = Ask;                               // [Case[5] FAILS TO PRE-PROCESS #define HERE ]


 // -------------------------------------------------------------------------------------------------------------------------
/*                                                       // [Case[6] OK */
#define               Ask_with_SomeOtherDEFINE_NAME aPtrToINSTANCE.Ask( False )
     double askINST = Ask_with_SomeOtherDEFINE_NAME;     // [Case[6] OK    TO CALL THE .Ask() METHOD AS THE PRE-PROCESSOR <_SYMBOL_TO_SUBSTITE_> WAS #define-d AS NON-COLLIDING]

//    **   *   ****        ****        *****        *****
//    ***  *  **   *      **   *       **           **   *
//    ** * *  **   *      **   *       ***          **    *
//    **  **  **   *      ** * *       **           **   * 
//    **   *   ****  **    ****   **   *****  **    *****  **
//                   *         *  
}; 
// ------------------------------------------------------------------

尾声:

  

正如我发布somewhere in some other MQL4-posts之后,在对基于 #define 指令的预编译器替换进行了大量测试后(出于版本管理目的等) ,我只能得出一个结论,试图避免使用这个功能,因为产生的问题要贵得多(令人惊讶的字符串处理限制,关于持续语言蠕变的不确定性,语法糖的不可预测的结果在下一次Build版本发布之后的技巧等)对于预期目的而言是有益的。

答案 1 :(得分:0)

宏替换应该在远离函数的地方声明。尝试将#define Ask MQL4::Ask()移到类声明之上或程序的第一行

UPD。在谈话之后,结果发现宏应该有不同的名称。

#define method (Class::method()) //doesnt work, 
#define method (Class::Method()) //or (Class::method_()) is fine