有什么情况你不想要包括警卫吗?

时间:2011-03-04 08:44:08

标签: c++ include-guards

我知道为什么包含警卫,#pragma once不是标准的,因此并不是所有编译器都支持等。

我的问题是另一种:

有没有明智的理由不让它们?我还没有遇到这样一种情况,理论上,如果不在其他地方包含文件中提供包含警卫,那将会有任何好处。有没有人有一个例子,其中有没有它们的实际好处?

我问的原因 - 对我而言,他们似乎非常多余,因为你总是使用它们,#pragma once的行为也可以自动应用于字面上的一切。

6 个答案:

答案 0 :(得分:9)

我见过根据在包含之前定义的宏生成代码的标头。在这种情况下,它有时希望将这些宏定义为一个(一组)值,包括标题,重新定义宏,然后再次包含。
每个看到这种情况的人都同意它是丑陋的并且最好避免,但有时候(如果所述标题中的代码是通过其他方式生成的话),这样做是较小的邪恶。

除此之外,我想不出一个理由。

答案 1 :(得分:5)

@sbi已经讨论过代码生成,所以让我举个例子。

假设您有很多项的枚举,并且您希望为每个元素生成一堆函数...

一种解决方案是使用这种多重包含技巧。

// myenumeration.td
MY_ENUMERATION_META_FUNCTION(Item1)
MY_ENUMERATION_META_FUNCTION(Item2)
MY_ENUMERATION_META_FUNCTION(Item3)
MY_ENUMERATION_META_FUNCTION(Item4)
MY_ENUMERATION_META_FUNCTION(Item5)

然后人们就这样使用它:

#define MY_ENUMERATION_META_FUNCTION(Item_) \
  case Item_: return #Item_;

char const* print(MyEnum i)
{
  switch(i) {
    #include "myenumeration.td"
  }

  __unreachable__("print");
  return 0; // to shut up gcc
}

#undef MY_ENUMERATION_META_FUNCTION

这是好还是黑客取决于你,但显然每次在枚举中添加新值时都不必抓取所有实用程序函数。

答案 2 :(得分:3)

<cassert>
<assert.h>

“每次根据NDEBUG的当前状态重新定义断言宏 &LT; ASSERT.H&GT;包括在内。“

答案 3 :(得分:0)

如果项目中有两个标题使用相同的包含保护,则可能会出现问题,例如:如果您有两个第三方库,并且它们都有一个使用包含保护符号(如__CONSTANTS_H__)的标头,那么您将无法在给定的编译单元中成功#include两个标头。更好的解决方案是#pragma once,但是一些较旧的编译器不支持此功能。

答案 4 :(得分:0)

假设您有第三方库,并且无法修改其代码。现在假设来自此库的包含文件会生成编译器警告。您通常希望在高警告级别编译自己的代码,但这样做会因使用库而产生大量警告。您可以编写警告禁用/启用程序标题,然后您可以将其包裹在第三方库中,并且它们应该能够被多次包含。

另一种更复杂的用法是Boost的预处理器迭代构造: http://www.boost.org/doc/libs/1_46_0/libs/preprocessor/doc/index.html

答案 5 :(得分:0)

#pragma曾经的问题,以及它不属于标准的原因是,它并不总是在任何地方都有效。如果两个文件包含在不同的路径中,编译器如何知道两个文件是否相同?

考虑一下,如果编译器出错并且未能包含应该包含的文件,会发生什么?如果它包含两次文件会发生什么,它应该没有?你会如何解决这个问题?

使用包含保护,最糟糕的情况是编译需要更长的时间。

编辑: 请查看comp.std.c ++上的这个主题“#ISO标准中的#pragma吗?”

http://groups.google.com/group/comp.std.c++/browse_thread/thread/c527240043c8df92