Reputation: 30046
GNU C and C++ offer the const
and pure
function attributes.
From the gnu online docs (emphasis mine):
In GNU C and C++, you can use function attributes to specify certain function properties that may help the compiler optimize calls or check code more carefully for correctness. For example, you can use attributes to specify that a function never returns (noreturn), returns a value depending only on the values of its arguments (const), or has printf-style arguments (format).
Where the const attribute seems to be a subset to pure, also taken from the gnu docs:
The const attribute imposes greater restrictions on a function’s definition than the similar pure attribute. Declaring the same function with both the const and the pure attribute is diagnosed.
With C++ 11, the constexpr
specifier was added.
When applied to functions, is there a difference between the const attribute and the constexpr specifier? Does GCC apply different optimizations?
A similar sounding question is Difference between `constexpr` and `const` . But I think this is not a duplicate. My question is specifically about the function attribute const
, which seems to have overlapping functionality with constexpr
.
Upvotes: 6
Views: 1630
Reputation: 28783
There is very little overlap between the them. Here is a function that is gnu::const
(and therefore gnu::pure
) but cannot be constexpr
:
[[gnu::const]] int f() {
struct s {
int m;
};
union {
s a;
s b;
};
a.m = 1;
return b.m;
}
You cannot read from the common initial subsequence of a union in a constant expression, so this function never produces a constant expression.
The following is a function that is constexpr
but cannot be gnu::pure
(and therefore cannot be gnu::const
):
constexpr void f(int & x) {
x = 1;
}
This writes to memory, which gnu::pure
functions cannot do.
constexpr
just means that it can be called at compile time. This has overlap with gnu::const
and gnu::pure
in that you cannot write to global variables or access volatile memory (all IO operations access volatile memory from C++'s point of view), but they each have other restrictions that make them distinct.
In C++11, constexpr
was much more limited. You could not write to any reference parameters, so I think C++11 constexpr
was a strict subset of gnu::pure
. The following is an example of a C++11 constexpr function that cannot be marked gnu::const
, however:
[[gnu::pure]] constexpr int f(int const & x) {
return x;
}
Upvotes: 1
Reputation: 23497
Another difference is that a __attribute__ ((const))
function must return the same output value for the same argument (if I am not wrong; it's the first time I see this attribute ;). That does not need to hold for constexpr
functions.
An academic example:
constexpr int rand(int n)
{
std::string_view sv(__TIME__);
return sv.back() % n;
}
std::array<int, rand(10) + 1> a; // exemplary usage
Though rand
is constexpr
, it may produce different output for the same input argument.
Upvotes: -2
Reputation: 238311
When applied to functions, is there a difference between the const attribute and the constexpr specifier?
There are differences.
Firstly, C does not have constexpr, so you cannot take advantage of it in that language.
Calls to constexpr function can be constant expressions. As such, their result can be used for example as the size of an array. The GNU attributes cannot be used to achieve the same (ignoring GCC VLA language extension).
Constexpr functions are good for taking advantage of pre-calculation at compile time. The GNU attributes are still useful for allowing the compiler take advantage of runtime constness. For example, let's say there is a function that cannot be constexpr - perhaps because it calls a non-constexpr function. But we may know that every call to the function produces same output with no side-effects. Const attribute allows the compiler to not repeat redundant calls.
Another difference is that constexpr functions must be defined inline. Non-constexpr functions don't need to be defined inline.
Upvotes: 4