我需要不断更改
#include
头文件名(有很多),所以我需要类似这样的东西:
#define NUMBER 23
#include "file${NUMBER}.h"
int main()
{
return run();
}
//Inside header files:
#pragma once
int run();
我知道我可以将
${NUMBER}
替换为 23
,但我不想手动执行此操作,因为我也将在其他代码行中使用它。另外,我不想在运行时包含所有这些。
如果这是不可能的,还有哪些其他简单的替代方法可以做到这一点?
我正在使用 Visual Studio。
我也尝试过这个,但没有成功:
#define s1 "file"
#define s2 "23"
#define concat(a,b) a##b
#define s3 concat(s1,s2)
#include s3
这不是“文本宏”,而是宏定义。
${NUMBER}
是 C++ 标准中未定义的预处理器指令语法,不能直接使用引号。
如果您阅读
#include
指令的文档,您会遇到类似的情况
其中#include X h-char-sequence Y new-line
在一系列实现定义的位置中搜索由
和X
分隔符之间的指定序列唯一标识的标头Y
X
和
Y
是
<
和
>
或引号
"
。那里的文字是逐字使用的。解决这个问题的唯一方法是对整个序列使用宏定义,有时某些库会使用宏定义,例如通过升压。这种形式的
#include
看起来像
#include pp-tokens new-line
pp-tokens
是合法序列,与文本中其他任何地方一样处理。它应该导致上述两种形式之一,否则
#include
指令的行为未定义 - 可能会导致错误,但某些实现会忽略空序列。要创建用引号括起来的文本,需要一定的技巧:
// #define NUMBER 23 // rather use -D compiler flag?
// ## operator is concatenation operator
// which joins verbatim parameter with surrounding
// text to form something lexem-like
#define FILE_NAME_NUM(f,N) f##N.h
// # is stringization operator which can be used only on a parameter
#define STRINGIFY_(s) #s
// this is required to process the paramater `macro` before # would
// surround it by quotes
#define STRINGIFY(macro) STRINGIFY_(macro)
#define NUMBERED_HEADER(f,N) STRINGIFY(FILE_NAME_NUM(f,N))
// unfolds into #include "file23.h"
#include NUMBERED_HEADER(file,NUMBER)
看起来有些多余,但这是必要的,因为预处理器使用了非常简单的替换算法。类似函数的宏定义不是函数。预处理器的作用:
NUMBERED_HEADER(file,NUMBER)
,会寻找文件和
NUMBER
的替代品。
NUMBER
,将其替换为23,结果:
NUMBERED_HEADER(file,23)
NUMBERED_HEADER
并通过替换每个参数来将其替换为
STRINGIFY(FILE_NAME_NUM(file,23))
FILE_NAME_NUM
并通过替换每个参数来将其替换为
file23.h
macro
中的
STRINGIFY(macro)
替换为
file23.h
由于 s
,
STRINGIFY(s)
中的 "file23.h"
被 #
替换
<
和
>
会更简单,可以直接使用:
// still required for ##
#define FILE_NAME_NUM(f,N) f##N.h
#define NUMBERED_HEADER(f,N) <FILE_NAME_NUM(f,N)>