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.
#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