4

I am going through Implementation defined behavior control

and there is the following text in relation to #pragma once:

Unlike header guards, this pragma makes it impossible to erroneously use the same macro name in more than one file.

I am not sure what this implies. Can someone explain?

TIA

Vinod
  • 925
  • 8
  • 9

3 Answers3

10

Example:

// src/featureA/thingy.h
#ifndef HEADER_GUARD_FOR_THINGY
#define HEADER_GUARD_FOR_THINGY
struct foo{};
#endif


// src/featureB/thingy.h
#ifndef HEADER_GUARD_FOR_THINGY
#define HEADER_GUARD_FOR_THINGY
struct bar{};
#endif


// src/file.cpp
#include "featureA/thingy.h"
#include "featureB/thingy.h" // oops, this file is removed by header guard
foo f;
bar b;

Header guard macros require meticulous effort to keep them unique. #pragma once does that automatically.

In fairness and for completeness, let me mention the drawback (also in the linked page): #pragma once does not recognize the same file if it is included from multiple paths. This may be a problem for projects with an exotic file structure. Example:

// /usr/include/lib.h
#pragma once
struct foo{};


// src/ext/lib.h
#pragma once
struct foo{};


// src/headerA.h
#pragma once
#include <lib.h>

// src/headerB.h
#pragma once
#include "ext/lib.h"

// src/file.cpp
#include "headerA.h"
#include "headerB.h" // oops, lib.h is include twice
foo f;
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 1
    While this is all correct, it doesn’t mention the problems that `#pragma once` has that don’t exist with include guards. – Pete Becker Feb 23 '19 at 03:46
  • @PeteBecker that's not what was aked for. But I now added it for completeness regardless. – eerorika Feb 23 '19 at 03:47
2

Let's say you have a header file, File1.h. You created File1.h with:

#ifndef FILE_1_H
#define FILE_1_H

// Contents of File1.h

#endif

There is nothing in the language to prevent other header files from using the same macro, FILE_1_H, as include guards.

  1. A header file in a library you use could have defined that.
  2. You could use the same header guards in File2.h in your own code base due to copy and paste error.

When that happens, only one of the .h files can be #included in a .cpp file. In the best of cases, you will get compiler errors that will allow to fix the problem. In the worst of cases, you will end up using the wrong type or function and the problem will manifest itself at run time.

For these reason, the include guards are not robust and subject to user error.

However, if your compiler supports it and you use

#pragma once

in all your header files, such errors will be avoided.


Please note that use of

#pragma once 

has its own set of downsides. See the following for more on that:

Is #pragma once a safe include guard?
What are the dangers of using #pragma once?

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

Include guards look like this:

#ifndef SOME_NAME
#define SOME_NAME

// The header file contents

#endif

While there are naming conventions, there's nothing to enforce what the macro (SOME_NAME in this case) will actually be called. If you try to include two header files that use the same macro name, the compiler won't see the contents of the second file since that file's #ifndef ___ will fail (the macro was already defined in the first file).

This problem doesn't exist with #pragma once.

Kevin
  • 6,993
  • 1
  • 15
  • 24
  • While this is all correct, it doesn’t mention the problems that `#pragma once` has that don’t exist with include guards. – Pete Becker Feb 23 '19 at 03:45
  • @PeteBecker I was answering the question in the OP, which was an explanation of the quote. – Kevin Feb 23 '19 at 03:47
  • Yes, but you didn’t mention that the quote is misleading. – Pete Becker Feb 23 '19 at 03:49
  • @PeteBecker I don't see how it's misleading. It explains a downside to header guards which `#pragma once` doesn't have. The next sentence of the quote explains the downside of `#pragma once`: *"On the other hand, since with `#pragma once` files are excluded based on their filesystem-level identity, this can't protect against including a header twice if it exists in more than one location in a project."* – Kevin Feb 23 '19 at 03:53