Mic*_*ael 14 c c++ c-preprocessor
A类使用用C编写的库.这个库提供了一些在A中使用的数据类型和常量.不幸的是,该库还在其头文件中定义了宏,它与main.cpp或其他使用A的类中的C++代码冲突.
当Ah被包含在某处时,如何防止执行c_library.h的宏?我也愿意接受架构改变,但我宁愿不接触C库.
当然,还有#undef指令.但这意味着每个宏或每次碰撞都会进行大量的手动操作.(好吧,没有太多 - 但嘿,这一定可能更优雅吗?)
码:
//main.cpp
#include "A.h"
...
A a(...)
...
std::max(x, y); // oops, problem since max is defined as macro in c_library.h
...
//A.h
#include "c_library.h"
class A{
public:
A(...);
static void callbackForCLibrary(datatypeOfCLibrary d){...}
private:
private datatypeOfCLibrary1;
private datatypeOfCLibrary2;
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*k B 18
您已经了解了该#undef选项,它可以满足您的需求.
但是还有另一种选择.您可以完全隐藏您的用户A使用库的事实C:在标题和类定义中定义您自己的类型和接口,A并从A标题中删除库包含.然后在您的实现文件中,您可以包含库头并以任何需要的方式使用库,同时隐藏c_library.h来自用户的包含.这样做的另一个好处是可以减少类用户,类和它所依赖的库之间的耦合.
Rob*_*b K 10
您可以创建一个"wrap_c_library.h",它类似于:
#ifndef WRAP_C_LIBRARY_H
#define WRAP_C_LIBRARY_H
#include "c_library.h"
#undef TROUBLESOME_MACRO_FROM_C_LIBRARY
#endif // WRAP_C_LIBRARY_H
Run Code Online (Sandbox Code Playgroud)
可能(不确定这在实践中的效果如何)#undef并不一定意味着手动工作 - 您可以自动生成第二个文件以包含#undef第一个头中的所有定义.
例如,给这个标题:
#define A(X, Y) [X ; Y]
#define B(X, Y) {X...Y}
#define C this is C
#define D this is D
Run Code Online (Sandbox Code Playgroud)
...运行以下简短脚本:
gcc -undef -dN -E foo.h > undef_foo.h
sed -i ".bak" 's/#define[ \t]\([A-Za-z0-9_]*\)/#undef \1/g' undef_foo.h
gcc -undef -dD -E - < /dev/null >> undef_foo.h
sed -i ".bak" '/#[du]/!d' undef_foo.h
Run Code Online (Sandbox Code Playgroud)
...产生这个反标题:
#undef __STDC__
#undef __STDC_HOSTED__
#undef __DYNAMIC__
#undef A
#undef B
#undef C
#undef D
#define __STDC__ 1
#define __STDC_HOSTED__ 1
#define __DYNAMIC__ 1
Run Code Online (Sandbox Code Playgroud)
基本思路:获取包含的所有定义的列表foo.h.-undef -dNGCC 的参数最小化了系统提供的内容,这些内容将包含在此列表中(对我而言,最少为三个,不确定这是多么一致),以最小化抵押品并简化输出.然后#define用等效#undef行替换所有行(-dN通过不列出替换使这更容易).然后将仍然包含的少数系统定义的宏GCC附加到文件的末尾,以便恢复它们的值.最后,从文件中删除所有不是#define或的指令#undef.
用法:
#include "foo.h"
#include "undef_foo.h"
A(1, 2)
B(3, 4)
C
D
Run Code Online (Sandbox Code Playgroud)
运行gcc -E并观察不扩展的宏.
拥有更好脚本技能的人可能会使这更好,但这是基本的想法.
1)对于任何特定的宏,你可以用"禁用"它#undef.
2)如果你不想要特定标题中的任何定义:就是不要#include它.
3)如果标题被隐含地包含在其他内容中,并且您仍然想要"禁用"整个标题,那么您可以#define在首次包含之前进行标题保护.
4)我无法想象这些选项中的任何一个都适用于"std :: max()":
http://en.cppreference.com/w/cpp/algorithm/max