经过更长时间的研究,我终于找到了最优雅的解决方案。定义风格取决于是否要初始化变量。
如果变量不需要初始化,只需要一个头文件:
template <int TimerCode>
int TCCRB;
是的,它是而且必须如此简单。不要像我们通常对头文件中的变量那样添加“静态”或“外部”关键字。它将通过编译并作为所有 CU 之间的全局变量模板工作。相同的实例将共享相同的实际变量,即一个 CU 中的更改将影响其他 CU,只要它们具有相同的模板参数。
我们知道,如果你在头文件中定义了一个没有必要关键字如“static”或“extern”的变量,如果头文件包含在多个CU中,则会导致重新定义错误。“静态”告诉编译器将每个 CU 的这个变量复制为单独的变量,因此一个 CU 中的更改不会影响另一个 CU 中的更改。相反,“extern”告诉编译器这里的这个变量只是一个声明。它仅在其中一个 CU 中定义和拥有,其他 CU 应仅保留对其的引用或符号。因此,一个 CU 中的更改将影响其他 CU。
但是,变量模板既不是静态定义也不是外部声明。这是对编译器的一条特殊指令:查找对该模板的所有引用,将相同模板参数的引用组合起来,并为每个唯一实例自动生成一个定义!这次编译器负责避免重新定义:它扫描所有 CU,然后自己生成唯一的定义!
如果您不想给变量一个初始值,并且如果有太多可能的实例需要一一列出,这种自动定义非常方便。但是,如果您确实想要一个初始值,则必须自己定义它,并且您需要一个单独的 CU 来拥有这些变量以避免重新定义:
//In the header file:
template <int TimerCode>
extern int TCCRA;
//In the CPP file:
template <>
int TCCRA<1> = 2;
template <>
int TCCRA<2> = 5;
//Naturally you have to provide initial values for all possible instances …
对于这种情况,“extern”关键字是必要的,因为您在专门提供的 CU 中明确定义了所有有效实例,其他 CU 必须引用此定义。编译器本身不应生成随机定义。这很像普通的全局变量定义,只是增加了一些模板语法。但是,用户只能使用 CPP 文件中提供的实例。这也很自然,因为只有已知实例才能提供初始值。
我在互联网上发现很少有关于这个主题的教程。希望我的经历可以帮助到更多的人~