使用伪模板替代 C++ 模板(基础篇)
用宏伪模板绕过 MQL5 的泛型缺失
MQL5 不像 C++ 那样原生支持模板,想在多种类型上复用同一套逻辑时,直接写重载函数会迅速膨胀代码量。社区里较早(2013-12-31 发布,浏览 2558、评论 11)就有人用宏模拟出模板行为,思路是用预处理宏把类型名拼进函数名与内部变量声明。
下面这段宏定义了一个可作用于任意数值类型的求和函数壳:
[CODE]
#define TEMPLATE_SUM(TYPE) \
TYPE Sum_##TYPE(TYPE a, TYPE b) { \
return(a + b); \
}
[/CODE]
逐行看:第一行 #define TEMPLATE_SUM(TYPE) 声明宏名并接收类型参数;第二行 TYPE Sum_##TYPE(TYPE a, TYPE b) 用 ## 把类型拼进函数名,生成如 Sum_double;第三行 { return(a + b); } 是具体实现,对传入的同类数值做加和。
实际用的时候补一行 TEMPLATE_SUM(double) 就能在 MT5 里得到 Sum_double。外汇与贵金属杠杆高、滑点无常,这类工具只解决代码复用,不暗示任何行情方向。
class="macro">#define TEMPLATE_SUM(TYPE) \ TYPE Sum_#class="macro">#TYPE(TYPE a, TYPE b) { \ class="kw">return(a + b); \ }
「为什么自己造一套模板」
在 MT5 的 MQL5 社区论坛里,关于「语言层面缺少标准模板(template)实现」的吐槽反复出现,说明这是实盘脚本开发者普遍碰到的痛点。 作者早期曾向 MQL5 开发团队提过相关需求,但被明确拒绝,这直接促使他用自定义方案去补齐这块能力缺口。 本文系列就是这套自研模板机制的研究记录,第一篇先交代动机:不依赖官方语法糖,用现有语言特性硬凑出可复用的泛型结构,方便后续指标和 EA 的参数化封装。
◍ C 到 C++:系统级语言的两次跃迁
C 语言诞生之初就瞄准了系统任务:它不抽象执行环境,只给程序员直接操作内存、搭控制结构和做模块管理的手段。除了这些,其余功能全丢给运行时库,这也是有人嘲讽它是“结构化汇编”的原因,但简单性与能力的比值确实被它拉到了新高度。 到了八十年代后期,C 把 Fortran 从主导地位挤下,成为全世界程序员最常用语言,大学里 Unix 与 C 的同步分发进一步推了它一把。不过它太低级了——处理器位数一变,大量直接做地址运算的 C 程序就出毛病;同时它又缺高级语义,没有数据抽象、多态和异常,写业务常被底层技术细节绑架。 八十年代初 AT&T 贝尔实验室的 Bjarne Stroustrup 着手扩展 C,起名“带类的 C”。核心机制是 class:你描述对象内部状态加一组访问函数,目的之一是抬高已有代码的复用率。 C++ 不止加了类,还落了结构化异常处理、模板等机制,主线始终是在保持 ANSI C 完全兼容的前提下,用高级构造扩可能性。对外汇/贵金属量化脚本而言,这种演进意味着 MT5 里的 MQL5 既能贴近底层算价格,也能用类封装策略模块,但杠杆类交易高风险,回测漂亮不等于实盘概率占优。
用伪模板绕开 MQL5 的类型替换限制
MQL5 编译器本身不支持 C++ 那种模板,官方说法是引入类型替换机制可能让编译器崩溃并带来反编译风险,所以类型替换这件事在语言层面是被放弃的。但 C++ 模板的本质,是编译器在调用处按实际类型把函数或类重写一遍——机器码在编译期生成,源码里写一次,二进制里可能生成多次。 既然不能改编译器,就只能把这套逻辑从「二进制生成」挪到「文本编写」阶段。思路是:不依赖语言标准的模板,而是在写代码时手动做类型替换,相当于自己当预处理器。这种写法被叫做「伪模板」,它解决的还是老问题——减少交易者重复敲代码的工作量,而不是缩小最终 EX5 体积。 对外汇、贵金属 EA 开发来说,这种手法高风险伴随高自由度:宏式替换若手滑写错类型,MT5 只会在编译报错甚至静默逻辑偏移,回测和实盘都可能偏离预期。建议开 MT5 新建一个空指标,先拿两种数据类型练一遍替换,确认编译产物符合直觉再扩到策略类。