lhk
lhk

Reputation: 30046

GNU const/pure attributes vs constexpr

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

Answers (3)

David Stone
David Stone

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

Daniel Langr
Daniel Langr

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

eerorika
eerorika

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

Related Questions