Are constexpr functions implicitly static?
Asked Answered
C

2

13

If I define a function in my program.cpp:

constexpr bool isThree(const int number)
{
  return number == 3;
}

is that any different from declaring it static?

static constexpr bool isThree(const int number)
{
  return number == 3;
}

It seems that those should be equivalent, since constexpr means the function is inline and therefore not shared among compilation units.

Are constexpr global functions implicitly static?

Campuzano answered 16/5, 2019 at 15:39 Comment(4)
Your reasoning would imply that static and inline are the same, which they are not. That's unrelated to the function being constexpr, in fact.Matty
constexpr is a compile time feature, where inline/static are runtime features.Tillford
The meaning of constexpr is more restricted than static. The meaning is that given a particular input value the return value is always the same, and the copiler ought to be able to work it out completely during compilation. A static function simply only has scope within one compilation unit. The returned value could change depending on other variables it accesses.Vasily
@MichaelChourdakis how is inline a run-time thing? It is a link time thing primarily (ODR - and a possible compile-time hint). Run-time the code is already generated and inline is long gone/means nothing. static also primarily affects linkage/visibility, not run-time behaviour.Groundwork
P
14

constexpr functions are implicitly inline.

inline is a linking feature. An inline function with definitions in different compilation units is not an error; if their definitions vary, your program is ill-formed no diagnostic required, but if they have the same definition then all but one version is discarded and that version is used.

static, on a non-method function, is also a linking feature. A static definition is not shared outside of its compilation unit; the compilation unit does not 'advertise' that it has a definition for isThree.

static on a method function has nothing to do with linking. In that case, it just means that this is not implicitly passed to the function. A method with/without this it doesn't work has differences, but they are mostly unrelated to them being constexpr. Note that in at least a constexpr method that doesn't use this can still be constant evaluated. Some versions of make constexpr methods implicitly const; does not.

&isThree in one compilation unit and &isThree in another can (and usually do) vary when static (barring aggressive ICF, which is a matter for a different question). When inline they may not vary.

inline functions are shared between compilation units. Their full definition is also often visible in all compilation units aware of it, so it makes compiler "inlining" (as opposed to the keyword) your code easier. static are not. constexpr functions are implicitly inline, but not implicitly static.

Note that constexpr functions can be evaluated in a runtime context sometimes. When evaluated in a compile time context, their inline vs static or linkage state really doesn't matter.

constexpr means other things as well, but you wanted to know the difference between two different constexpr declarations, and none of those meanings change.

Photogram answered 16/5, 2019 at 15:48 Comment(2)
static means different things in different contexts, but you mentioned only one meaning. Answer could be improved by mentioning all. 🙂Groundwork
@JesperJuhl Sure, it is possible that isThree is declared in a class, so added a paragraph about that.Photogram
H
4

constexpr functions are not implicitly static. They have the same linkage as non-constexpr functions:

// external linkage
constexpr int f1(int x) { /* ... */ }

// internal linkage
static constexpr int f2(int x) { /* ... */ }

// internal linkage
namespace {
constexpr int f3(int x) { /* ... */ }
}

// no linkage
void enclosing() {
    struct S {
        constexpr int f4(int x) { /* ... */ }        
    };
}

When a constexpr function has external linkage, it has the same address in all translation units. When it has internal linkage, there is a different copy in each translation unit, and those copies have different addresses. However, I believe the result of calling a constexpr function should not depend on whether it has internal or external linkage (since constexpr functions may not contain static variables).

Howzell answered 16/5, 2019 at 16:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.