【问题标题】:Does Visual Studio have a namespace-sensitive macro-substitution option?Visual Studio 是否有命名空间敏感的宏替换选项?
【发布时间】:2011-07-28 22:30:49
【问题描述】:

我所说的是找到一种方法来避免<windows.h> 中的宏污染我正在编写的任何项目。

摘自windows.h

#ifdef UNICODE
#define LoadImage  LoadImageW
#else
#define LoadImage  LoadImageA
#endif // !UNICODE

#ifdef UNICODE
#define GetMessage  GetMessageW
#else
#define GetMessage  GetMessageA
#endif // !UNICODE

大多数宏(超过 99%)我都可以接受,但其中一些我无法避免。

我的想法是,因为我总是在我的特定框架中限定函数调用,例如ImageTool::LoadImage,Visual Studio 应该有足够的线索表明我没有引用 Windows API,它们都在根命名空间中,即 ::LoadImage。但是 MACRO 系统似乎没有那么聪明。

是否有编译器或预处理器选项可以启用它?

【问题讨论】:

  • 在包含<windows.h>之前尝试定义WIN32_LEAN_AND_MEAN
  • @Kerrek SB:谢谢,我试过了。没用。
  • 不确定问题出在哪里。您不应该在自己的代码中使用同名的宏。您应该将所有自己的代码放在自己的命名空间中,以确保与(不幸的是)全局命名空间中的 Windows 标头定义的函数没有冲突。
  • 我们更喜欢全限定名称而不喜欢使用命名空间 xxx...
  • @Cody: <windows.h> 是 Microsoft 包含文件。更糟糕的是,我刚刚发现它包含在框架头文件中 - 我不妨修改框架头文件(或<windows.h>)以满足我的需要。

标签: c++ visual-studio macros


【解决方案1】:

宏替换基本上是简单的文本替换,甚至在正确的编译器开始解析代码之前就完成了。因此,他们不知道名称空间或纯词法级别之上的 C++ 语法的任何其他部分。

避免替换标识符的直接方法是删除宏:

#ifdef LoadImage
#undef LoadImage
#endif

这当然也将阻止以下代码访问名为 LoadImage 的 Windows API。

【讨论】:

  • 谢谢。如果我需要访问 Windows API,我可以使用他们的“真实姓名”,例如::LoadImageW 包括正确的后缀。我只是想知道 VC++ 预处理器是否可以选择至少 lex 范围解析运算符。
  • 它被称为 pre-processor 是有原因的。 ;)
  • 预处理器必须在“令牌”级别进行解析。否则,它无法正确替换可能是字符串文字一部分的字符串。因此,预处理器有正确的知识,即范围解析运算符"::" 在某些内容之前。这个标记很容易解析 - 两个连续的冒号(或空格分隔的冒号)没有意义。
  • @rwong:这将违反 C 和 C++ 标准( 两者都适用)。
【解决方案2】:

您将接受它 - 在 Windows 平台上您无法避免这些宏。 C/C++ 预处理器世界中没有宏名称间距。但是,您可以在包含任何 Windows 标头之前定义和实现所有代码 - 但我相信这是不可能的。

【讨论】:

  • 我决定制作<windows.h> 的本地副本,根据我的喜好对其进行编辑,并将其命名为my_windows_is_leaner_and_meaner_than_yours.h,并将其存储为我的项目头文件之一。我知道我无法重新分发该文件;我的情况没问题。
  • 不值得痛苦!您需要非常定期地维护标头,其他标头/库将无法按预期工作!警告你! :)
  • windows.h 仅针对 Windows Platform SDK 的每个版本进行更新 - 考虑到他们过去的发布周期的长度,我可以接受这个麻烦。
猜你喜欢
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
  • 2012-12-19
  • 2020-02-08
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多