On Tue, 26 Nov 2024 at 14:27, Michael Matz <m...@suse.de> wrote: > > Hello, > > I don't have anything to add to the threads topic itself, but was > triggered by something: > > On Tue, 26 Nov 2024, Jonathan Wakely wrote: > > > > > const size_t __bufsz = __deque_buf_size(sizeof(_Tp)); > > > ... > > > I wonder why "const" is useful here. > > > > Because if you don't initialize a constant expression, then you get a > > runtime call to __deque_buf_size instead, which then has to be > > inlined. > > Hmm? Are you saying there's a difference in inlining (or other) > behaviour between the two initializer lines in foo: > > extern int bla(void); > int foo (void) { > const int x = bla(); > int y = bla(); > return x + y; > }
No, that's not what I'm saying :-) > > That would be surprising. Would it change if 'bla' was not a extern > function but something marked specially, constexpr or member function or > similar? But that would also be surprising to me. Being a member function makes no difference, but yes, I'm specifically talking about the case of calling a constexpr function. constexpr int bla() { return 2; } int foo (void) { const int x = bla(); int y = bla(); return x + y; } At -O0 this is one instruction smaller due to the const. Adding const to y removes another instruction. > I.e. ... > > > Using the call to initialize a const size_t ensures it's a constant > > expression, and there's nothing for the inliner to do. > > ... why would a cv qualifier on the non-reference LHS of an initialization > put any constraints on the kind of expressions on the RHS? Because in C++ when a const int is initialized by a constant expression that const int becomes an integral constant: const int x = 1; // OK, x is a constant expression: static_assert( x == 1 ); char arr[x]; // Not a VLA, C++ doesn't have VLAs. This isn't true for plain 'int' because obviously it's not a constant :-) it's value can change. In the bla() example above, the call bla() is a constant expression when used to initialize a const int, so the compiler is required to evaluate it at compile time. When used to initialize a non-const int, it's just a normal runtime function call. The compiler is permitted but not required to evaluate it at compile time (and of course it can inline it and constant-fold it and end up with a constant result, but that's an optimization and not the same as a "constant expression" required by the language semantics). In pure C++11 code I'd make it more explicit and write: constexpr int x = blah(); This makes it more obvious that we're initializing a constant expression. But the std::deque code needs to compile as C++98, which doesn't have the constexpr keyword. We could write it: #if __cplusplus >= 201103L constexpr #else const #endif int x = blah(); But luckily we don't need to, because the language says the two are equivalent (for integer types, not necessarily for other types), so we can just say 'const int' andhave our cake and eat it too.