Compiler errors 如何定义指向同名静态类方法的全局宏?
我有以下MQL4/5代码:Compiler errors 如何定义指向同名静态类方法的全局宏?,compiler-errors,syntax-error,mql4,mql5,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() { do
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()
不必重命名它,同时仍将其保留在静态类方法中?宏替换应该在函数之外的某个位置声明。尝试将define Ask MQL4::Ask移到类声明上方或程序的第一行 UPD。对话结束后,宏应该有不同的名称
#define method (Class::method()) //doesnt work,
#define method (Class::Method()) //or (Class::method_()) is fine
是的,但是…,不!定义替换很好,但是。。。但是Ask是一个保留字,这会使编译器感到困惑。
问题实际上是编译器预处理器的能力有限,而不是.method的同名
define指令(包括非参数和参数)的替换功能在已发布的MQL4/5语言语法的限制下进行了测试
案例[6]最终证明,
这个班。可以具有相同的名称。Ask,但不能与define-s相同
后记:
正如我所发布的,在对基于define指令的预编译器替换(用于版本管理)等的功能进行了广泛测试后,我只能得出一个结论,即尽量避免使用此功能,因为由此产生的问题比令人惊讶的字符串处理限制要昂贵得多,关于持续的语言爬行的不确定性,下一个构建版本后语法糖把戏的不可预测的结果等,都不利于预期目的
它不会有任何区别,因为编译器不会在函数中看到它。为了方便起见,它只是放在Ask方法定义之后。看:您的代码和输出-将宏移开并放入宏中,顺序并不重要,但在您的代码中,您已经将Ask重命名为Ask,那么它就可以正常工作了。但我希望将点Ask宏显式地放入MQL4::Ask。使用带大写字母的ASK不是MQL4中的标准,因为在MQL5下运行的现有MQL4代码将使用该类,该类将使用ASK,而不是ASK。因此,改变名字的方法是我想要避免的一种方法。如果将函数重命名为ask-它可以工作。也许它不想让宏和函数名相等,也就是说,如果不重命名变量或方法,这是不可能的?“Ask是一个保留字,这会混淆编译器”这是不正确的,如果在整个代码中将Ask更改为Foo,编译器将显示关于太复杂宏的相同错误,所以这不是一个保留字。在这种情况下[id]?嗯,没有人可以重命名硬编码系统。接下来,最薄弱的一点是define-pre-compiler替换,它依次替换每个的所有外观,之后lexer通常会死机。抱歉,这超出了MQL4/5端代码设计的控制范围。您的第一句话是“Ask是一个保留字,这会混淆编译器”。MQL5中的Ask变量不存在,同样的情况也存在,因此它与保留字无关。我认为主要的问题是宏定义的值中有宏名称,所以每个Ask都会被它的值替换,然后重复替换后会发生同样的情况,直到编译器意识到它太复杂时,进行了几次迭代。如果取消注释并重新测试不同的[Case[id]-s,错误消息会有所不同,根据冲突开始的位置不同,但通常会显示预编译器替换的发散恐慌与lexer恐慌相结合,因为中间表示的复杂性不断增加,它无法在代码结构分析中令人满意地终止,并在大约30个嵌套级别后在恐慌状态中出现。
//+------------------------------------------------------------------+
//| 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]
// ** * **** **** ***** *****
// *** * ** * ** * ** ** *
// ** * * ** * ** * *** ** *
// ** ** ** * ** * * ** ** *
// ** * **** ** **** ** ***** ** ***** **
// * *
};
// ------------------------------------------------------------------