有没有什么情况是你不希望有警卫的?

发布于 2024-10-20 06:38:35 字数 272 浏览 1 评论 0原文

我知道为什么存在包含保护,并且 #pragma Once 不是标准的,因此不被所有编译器等支持。

我的问题是另一种类型:

是否有任何明智的理由不拥有它们?我还没有遇到过这样的情况,从理论上讲,在本来要包含在其他地方的文件中不提供包含防护会有任何好处。有没有人有一个例子来说明没有它们有实际的好处?

我问的原因 - 对我来说,它们似乎非常多余,因为您总是使用它们,并且 #pragma Once 的行为也可以自动应用于几乎所有内容。

I know why include guards exist, and that #pragma once is not standard and thus not supported by all compilers etc.

My question is of a different kind:

Is there any sensible reason to ever not have them? I've yet to come across a situation where theoretically, there would be any benefit of not providing include guards in a file that is meant to be included somewhere else. Does anyone have an example where there is an actual benefit of not having them?

The reason I ask - to me they seem pretty redundant, as you always use them, and that the behaviour of #pragma once could as well just be automatically applied to literally everything.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦中的蝴蝶 2024-10-27 06:38:35

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

除此之外,我想不出任何理由。

I've seen headers that generate code depending on macros defined before their inclusion. In this case it's sometimes wanted to define those macros to one (set of) value(s), include the header, redefine the macros, and include again.
Everybody who sees such agrees that it's ugly and best avoided, but sometimes (like if the code in said headers is generated by some other means) it's the lesser evil to do that.

Other than that, I can't think of a reason.

清风疏影 2024-10-27 06:38:35

@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

这是好是坏取决于你,但显然,每次向枚举添加新值时不必爬行所有实用程序函数是有用的。

@sbi already talked about code generation, so let me give an example.

Say that you have an enumeration of a lot of items, and that you would like to generate a bunch of functions for each of its elements...

One solution is to use this multiple inclusion trick.

// 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)

Then people just use it like so:

#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

Whether this is nice or hackish is up to you, but clearly it is useful not to have to crawl through all the utilities functions each time a new value is added to the enum.

万劫不复 2024-10-27 06:38:35
<cassert>
<assert.h>

“每次断言宏都会根据 NDEBUG 的当前状态重新定义
<断言.h>包括在内。”

<cassert>
<assert.h>

"The assert macro is redefined according to the current state of NDEBUG each time that
<assert.h> is included."

独闯女儿国 2024-10-27 06:38:35

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

It can be a problem if you have two headers in a project which use the same include guard, e.g. if you have two third party libraries, and they both have a header which uses an include guard symbol such as __CONSTANTS_H__, then you won't be able to successfully #include both headers in a given compilation unit. A better solution is #pragma once, but some older compilers do not support this.

述情 2024-10-27 06:38:35

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

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

Suppose you have a third party library, and you can't modify its code. Now suppose including files from this library generates compiler warnings. You would normally want to compile your own code at high warning levels, but doing so would generate a large set of warnings from using the library. You could write warning disabler/enabler headers that you could then wrap around the third party library, and they should be able to be included multiple times.

Another more sophisticated kind of use is Boost's Preprocessor iteration construct:
http://www.boost.org/doc/libs/1_46_0/libs/preprocessor/doc/index.html

雪落纷纷 2024-10-27 06:38:35

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

想一想,如果编译器犯了一个错误,没有包含它应该包含的文件,会发生什么?如果它两次包含一个不应该包含的文件,会发生什么情况?你会如何解决这个问题?

对于包含防护,可能发生的最糟糕的情况是编译时间会更长一些。

编辑:
查看 comp.std.c++ 上的这个帖子“#pragma Once in ISO standard Yet?”

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

The problem with #pragma once, and the reason it is not part of the standard, is that it just doesn't always work everywhere. How does the compiler know if two files are the same file or not, if included from different paths?

Think about it, what happens if the compiler makes a mistake and fails to include a file that it should have included? What happens if it includes a file twice, that it shouldn't have? How would you fix that?

With include guards, the worst that can happen is that it takes a bit longer to compile.

Edit:
Check out this thread on comp.std.c++ "#pragma once in ISO standard yet?"

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文