Как определить глобальный макрос, указывающий на одноименный метод статического класса?

У меня есть следующий код 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()

без необходимости переименовывать его, сохраняя при этом в методе статического класса?


person kenorb    schedule 17.01.2017    source источник


Ответы (2)


ДА, но..., нет!
#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]

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

Эпилог:

Поскольку я разместил где-то в некоторых других сообщениях MQL4, после тщательного тестирования возможностей, доступных из подстановок прекомпилятора на основе директивы #define (для целей управления версиями и др.), я мог сделать заключение, чтобы попытаться избежать использовать эту функцию, так как возникающие проблемы были гораздо более дорогостоящими (неожиданные ограничения обработки строк, неопределенность в отношении продолжающегося языкового ползания, непредсказуемые результаты трюков с синтаксисом после следующих выпусков сборки и т. д.), чем выгода для намеченных целей .

person user3666197    schedule 17.01.2017
comment
Другими словами, вы говорите, что это невозможно без переименования переменной или метода? - person kenorb; 17.01.2017
comment
'Ask - это зарезервированное слово, которое сбивает с толку компилятор' это неправильно, если вы замените Ask на Foo по всему коду, компилятор покажет те же ошибки о слишком сложном макросе, так что это не о зарезервированное слово. - person kenorb; 17.01.2017
comment
В каком Case[id#]? Что ж, никто не может переименовать жестко запрограммированный системный регистр Ask. Далее, самым слабым местом является подстановка прекомпилятора #define, которая последовательно заменяет все появления каждого <_literal_symbol_to_substitute_>, после чего у лексера обычно возникает паника. К сожалению, это не зависит от разработки кода на стороне MQL4/5. - person user3666197; 17.01.2017
comment
Ваше первое предложение говорит о том, что («Спросить — это зарезервированное слово, которое сбивает с толку компилятор»). Переменной Ask в MQL5 не существует, и там происходит то же самое, так что речь не о зарезервированном слове. Я думаю, что основная проблема заключается в том, что значение определения макроса имеет в нем имя макроса, поэтому каждый Ask заменяется его значением, затем то же самое происходит после замены снова и снова, пока несколько итераций не осознают компилятор, что это слишком сложно. - person kenorb; 17.01.2017
comment
Да, об этом говорилось в предыдущем комментарии. - person user3666197; 17.01.2017
comment
Если вы раскомментируете и повторно протестируете разные [Case[id#]], сообщения об ошибках будут немного отличаться, различаться в зависимости от того, где началось столкновение, но обычно показывают расходящуюся панику подстановки перед компилятором в сочетании с паникой лексера при растущей сложности. промежуточное представление не может каким-либо образом удовлетворительно завершиться при анализе структуры кода и сдается в состоянии паники примерно после 30 уровней вложенности. - person user3666197; 17.01.2017

подстановка макросов должна быть объявлена ​​где-то вдали от функции. попробуйте переместить #define Ask MQL4::Ask() над объявлением класса или в первую строку вашей программы

УПД. после разговора выяснилось, что макрос должен иметь другое имя.

#define method (Class::method()) //doesnt work, 
#define method (Class::Method()) //or (Class::method_()) is fine
person Daniel Kniaz    schedule 17.01.2017
comment
Это не будет иметь никакого значения, так как компилятор не увидит его, как в функции. Он просто помещен после определения метода Ask для удобства. - person kenorb; 17.01.2017
comment
ты делаешь что-то неправильно. посмотрите: ваш код ссылка и вывод ссылка - достаточно удалить макрос и поместить все в () - person Daniel Kniaz; 17.01.2017
comment
Порядок не имеет значения, но в вашем коде вы уже переименовали Ask в ASK, тогда все работает нормально. Но я хочу явно указать макрос Ask в MQL4::Ask(). Использование ASK с заглавными буквами не является стандартной предопределенной переменной в MQL4, поскольку существующий код MQL4, работающий под MQL5 этот класс будет использовать Ask, а не ASK. Поэтому обходной путь изменения имен - это то, чего я хотел бы избежать. - person kenorb; 17.01.2017
comment
верно. если переименовать функцию в ask() - работает. возможно, он не хочет, чтобы имя макроса и функции было равным - person Daniel Kniaz; 17.01.2017