C++ Logo

std-proposals

Advanced search

Re: [std-proposals] #pragma once safer alternative

From: Muhammad <mail_at_[hidden]>
Date: Sun, 23 Mar 2025 06:34:03 +0000
OK, let's revisit #include for a minute. When the compiler hit the
#include directive it will add the content of that file in-place of that
directive and then will recursively scan the content for other #include
for expansion.

This is because a header file may look like this:

// FileA.hpp

#define MACRO1 1
#define MACRO2 "some value"

#ifndef DEBUG
# define M_D 3.14
#endif

#define MACRO3 3
#define MACRO4 "some other value"

// end FileA.hpp

Such file will cause the compiler to scan each time it got included to
insert the defined macros outside the #ifndef.

and here comes #pragma once to instruct the compiler that when it get
executed such file will not get included again. see the following
example

// FileB.hpp

#ifdef PART_1
# define VALUE 1
# pragma once
#endif
#ifdef PART_2
# define VALUE 2
#endif

// end FileB.hpp

// main.cpp
#include <iostream>
int main()
{
#include "FileB.hpp" // has no effect since the test macros not defined
#ifdef VALUE
     std::cout << "value is defined\n"; // will not get printed
#endif
#define PART_1
     std::cout << "PART_1 defined\n";

#include "FileB.hpp" // VALUE will get defined as well as the pragma
once
     std::cout << "value is :" << VALUE << '\n'; // will print 1

#undef PART_1
     std::cout << "PART_1 undefined\n";
#define PART_2 // has no effect now
     std::cout << "PART_2 defined\n";
#include "FileB.hpp" // the file already marked with #pragma once

     std::cout << "value is :" << VALUE << '\n'; // will print 1 again
     return 0;
}

the final result will be

PART_1 defined
value is :1
PART_1 undefined
PART_2 defined
value is :1

The #pragma once is optimization over the the inclusion guard. This
proposal is to add the #include once as a standard way to mark a file as
already included when the compiler execute it. so the FileB.hpp will be
written in the following way and it will give the same behavior.

// FileB.hpp

#ifdef PART_1
# define VALUE 1
# include once
#endif
#ifdef PART_2
# define VALUE 2
#endif

// end FileB.hpp

this will not remove #pragma once or the inclusion guard technique as
the first is a compiler-specific and the later is a valid preprocessor
construct. I will just be an addition that tells the compiler to stop
including that header file in any subsequent calls for it but in a
unified manner.

Received on 2025-03-23 06:34:07