C 预处理器或 C++ 魔法可以自动为每个文件创建一个对象?

标签 c c-preprocessor

我有一个函数,其行为可能需要根据调用它的文件进行修改(例如,为了增加调试跟踪输出)。此修改需要在不重新编译的情况下完成(例如,通过编辑配置文件或更改环境变量)。

作为满足这一需求的示例,我可以写 Function()如:

FunctionModifiable( const char* pszFile, int i );

然后这样制作一个宏:

#define Function( i ) FunctionModifiable( __FILE__, (i) )

FunctionModifiable()有义务检查pszFile比如说unordered_set<>在初始化期间填充,以查看是否需要激活特殊功能。

但是,该搜索的开销是负值(这是高性能软件,并且该函数被调用大量次),并且在这种情况下需要缓存一些每个文件的数据。我们可以消除搜索,并通过传入 not __FILE__ 来获取缓存信息的存储空间。而是一个指向辅助对象的指针。该对象需要文件名,以便在进行一次性初始化时,它可以查阅配置或环境变量或让您知道它是否需要特殊处理。

FunctionHelperObject fho( __FILE__ );

#define Function( i ) FunctionModifiable( &fho, (i) )  // C-style solution
#define Function( i ) fho.MethodModifiable( (i) )        // C++-style solution

好的,现在说我想避免用户必须定义​​ fho在每个文件中。 (除其他外,我们无法重写所有调用 Function() 的现有文件,尽管我们愿意重新编译它们)。

我的想法是将变量定义放入头文件中,这样任何程序都可以包含 Function() 的头文件。会得到 FunctionHelperObject fho( __FILE__ )免费。 (这样的定义将是 #pragma once 或由预处理器变量保护。

问题是 __FILE__此时将是 header 的名称,而不是顶级编译单元的名称。如果有一个__CFILE__符号,这将是解决方案,但没有。

最终我能想到的最好的方法有缺点:1)“可修改”方面只能在显式编写的源代码中使用它,2)你必须进行显式编写,3)开始变得有点复杂。在代码中,您想要添加修改行为的功能,可以编写 USE_MODIFIABLE_FUNCTION包含有问题的标题后的某个地方。这是一个创建 FunctionHelperObject 的宏上面,这次在正确的"file"中,所以 __FILE__将具有所需的值,并且还定义了一个如上所示的宏,该宏将屏蔽不可自定义的函数 Function()使用上面看到的两个宏之一。简而言之:前面的例子加上

#define USE_MODIFIABLE_FUNCTION FunctionHelperObject fho( __FILE__ );\n#define Function( i ) fho.MethodModifiable( (i) )

没有 USE_MODIFIABLE_FUNCTION 编写的代码只需调用不可定制的 Function()正常方式。

但这肯定是其他一些可接受的、可移植的方式来提供这种行为吗?虽然我专门讨论了 C 预处理器,但是否有任何 C++ 模板魔法或任何其他可行的方法?

最佳答案

缓存结果。

// in the header with Function macro
static FunctionHelperObject functionhelper;
static inline void FunctionModifiableInterface(const char *file, int i) {
    static initialized = 0;
    if (initialized == 0) {
        initialized = 1;
        functionhelper = FunctionHelperObject(file);
    }
    FunctionModifiable(&functionhelper, i);
}
#define Function(i) FunctionModifiableInterface(__FILE__, (i))

您无法预测用户会在哪里给您打电话Function(i) ,因此您无法预测 __FILE__ 的值。只需在第一次调用时初始化它,这也很棒,因为如果 Function 则不会初始化它。不被调用。你也可以这样做initialized检查里面FunctionHelperObject构造函数。

真正酷且难做的技巧是修改您的构建系统,以允许您传递带有已编译 C 文件的文件名的宏。因为构建系统一次编译一个 C 文件,所以这是可能的(遗憾的是编译器自己不这样做)。如果您使用cmakemake后端(或者实际上只是make本身),你可以做一些事情like this :

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__MY_FILE__='\"$(notdir $(abspath $<))\"'")

然后使用FunctionHelperObject fho(__MY_FILE__)就像你想的那样,因为__MY_FILE__仅取决于 make 的输出文件名.

关于C 预处理器或 C++ 魔法可以自动为每个文件创建一个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60484276/

相关文章:

c - 简单便携的 malloc 库

c - 从 C 程序观看 Linux Syslog 上的新条目

c - C 中的三元条件运算符

arduino - 我如何保证一个#define 比另一个大?

c++ - 模拟 Fn+F11 按键

c - 我怎样才能导致这个程序出现段错误? (帮助我找到一个缓冲区溢出漏洞)

有人可以解释一下这个语法 "#define HASH_IS_REAL(h_) ((h_) >= 2)"

fortran - Fortran 可变参数宏中的 CPP/GPP(加上 Fortran//连接)

预处理器和常量传播后的 C 代码

c++ - Clang 预处理器从 C++ 文件中去除注释