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