0

我有以下 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()并更新宏定义时它工作正常,
但是
我想了解
是否有任何其他解决方案而不必重命名它。

是否有任何语法可以定义可以理解以下宏的宏替换:

#define Ask MQL4::Ask()

无需重命名它,同时仍将其保留在静态类方法中?

4

2 回答 2

1

是的,但是……不!
#define替换工作正常,但是 ...
butAsk是一个保留字,这会使编译器感到困惑。

问题实际上在于编译器预处理器的有限功能,
而不是.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]

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

结语:

正如我在其他一些 MQL4 帖子中发布的那样,在对基于指令的预编译器替换(出于版本管理等目的)的可用功能进行了一些广泛的测试之后#define,我只能得出一个结论,尽量避免使用它feature,因为由此产生的问题(令人惊讶的字符串处理限制、关于持续语言蠕变的不确定性、下一个 Build 版本后语法糖技巧的不可预测结果等)比对预期目的有益得多。

于 2017-01-17T15:58:08.487 回答
0

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

UPD。交谈后发现宏应该有不同的名称。

#define method (Class::method()) //doesnt work, 
#define method (Class::Method()) //or (Class::method_()) is fine
于 2017-01-17T14:38:16.323 回答