pure is a function attribute which says that a function does not modify any global memory.
const is a function attribute which says that a function does not read/modify any global memory.
Given that information, the compiler can do some additional optimisations.
Example for GCC:
float sigmoid(float x) __attribute__ ((const));
float calculate(float x, unsigned int C) {
float sum = 0;
for(unsigned int i = 0; i < C; ++i)
sum += sigmoid(x);
return sum;
}
float sigmoid(float x) { return 1.0f / (1.0f - exp(-x)); }
In that example, the compiler could optimise the function calculate to:
float calculate(float x, unsigned int C) {
float sum = 0;
float temp = C ? sigmoid(x) : 0.0f;
for(unsigned int i = 0; i < C; ++i)
sum += temp;
return sum;
}
Or if your compiler is clever enough (and not so strict about floats):
float calculate(float x, unsigned int C) { return C ? sigmoid(x) * C : 0.0f; }
How can I mark a function in such way for the different compilers, i.e. GCC, Clang, ICC, MSVC or others?
In general, it seems that almost all compilers support the GCC attributes. MSVC is so far the only compiler which does not support them (and which also doesn't have any alternative).
First, it's useful to note that "const" is a more strict version of "pure", so "pure" can be used as a fallback if a compiler doesn't implement "const".
As others have mentioned, MSVC doesn't really have anything similar, but a lot of compilers have adopted the GCC syntax, including many which don't define
__GNUC__
(and some which sometimes do and sometimes don't, depending on flags).__has_attribute(pure)
and__has_attribute(const)
to detect them, but it's probably fine to just rely on clang setting__GNUC__
. This also includes compilers based on clang like emscripten and XL C/C++ 13+.__TI_GNU_ATTRIBUTE_SUPPORT__
) supports both.Of these, clang always defines
__GNUC__
and friends (currently to 4.2, IIRC). Intel defines__GNUC__
by default (though it can be suppressed with -no-gcc) as does PGI in C++ mode (but not in C mode). The others you'll have to check for manually.Oracle Developer Studio has also supported pragmas since it was known as Forte Developer 6. They're used a bit differently since they require you to specify the function name:
TI 6.0+ (at least) supports a
#pragma FUNC_IS_PURE;
pragma in C++ mode only. In C mode, it's#pragma FUNC_IS_PURE(funcname);
.Most of this can be hidden behind a macro, which is what I've done in Hedley:
This doesn't include the variants which would require the function names as an argument, but it still covers the vast majority of users, and it's safe to use everywhere.
If you don't want to use Hedley (it's a single public domain / CC0 header) it shouldn't be too difficult to replace the internal version macros. If you choose to do that, you should probably base your port on the Hedley repo instead of this answer as I'm much more likely to keep it up to date.