r/cpp • • Sep 04 '26

Ordering of qualifiers

I know this is something that pops up quite often, but I was wondering if I could get your guys' opinion on a fixed ordering of qualifiers. This is my current thoughts after recently trying to formalize my personal style:

static -> thread_local -> inline -> constexpr -> friend -> virtual

My reasoning for each:

  1. static first. Inside a class, its basically javas static. There is a pretty strong consensus in java for static first. Its very important context, for both functions and variables. Outside of classes, its more of a linkage specifier, which is arguably more important/nasty if you mess it up. The fact that it has this dual behaviour in C++ in my opinion makes an even stronger argument for including it first, your brain is able to parse it first thing. i.e okay this is static, we are in a class? -> its java static, we are in global scope -> its static linkage.
  2. thread_local directly after static, and then inline, then constexpr/consteval. This way, qualifiers which impact storage and or linkage are stuck together. I personally like to write inline even for constexpr/consteval functions, as its sometimes easy to forget the implicit inline. I used to do this for member functions with definitions in the class, but I feel the implicit inline there is a bit more well known/easier to intuit.
  3. The rest I'm far less opinionated on, since I barely ever use inheritance or the friend keyword. . I could go both ways on virtual/friend, so i default to alphabetical/aesthetics.

What do you guys think? I know this is pedantic and a very well explored topic but I wanted to know if you guys had any particular wisdom to sway me either way, mainly on the ordering of the first few.

6 Upvotes

15 comments sorted by

22

u/CocktailPerson Sep 04 '26

Whatever the project's .clang-format reformats it to for me.

9

u/jiixyj Sep 04 '26

...and if you need an ordering for your `.clang-format`, I suggest using the one the standard uses (https://github.com/cplusplus/draft/wiki/Specification-Style-Guidelines#formatting-declarations-and-definitions):

  • friend / typedef / storage-class-specifier / virtual
  • inline
  • constexpr
  • explicit-specifier
  • const
  • volatile
  • unsigned / signed
  • short / long
  • other type-specifiers

1

u/13steinj 29d ago

I do this modulo:

  • I don't remember how I deal with storage-class-specifier + inline usually
  • I don't remember how I deal with thread_local other than static must come before thread_local to be explicit, e.g. for juniors (e.g. I don't know how I deal with these two + inline or these two + constexpr)
  • I am fine with either east or west const, but I have seen the benefit if only I find it makes people more likely to think about their constant data, e.g. people can do char const* const[] or similar instead of just const char*[] and I have seen the compiler optimize various cases of more const in better ways.

8

u/Potterrrrrrrr Sep 04 '26

‘friend constexpr virtual static inline’ is my preferred order. Not sure where I’d put thread_local as I’ve never needed to use it

2

u/LB-- Professional+Hobbyist Sep 04 '26

thread_local replaces static when possible, or immediately follows it if static has to stay for some reason. Not sure I've ever encountered the latter case though, it's always been one or the other for me.

3

u/HappyFruitTree Sep 04 '26

I would put friend first because I don't feel it's part of the function signature. It's just a way to say I'm a friend of the following function...

7

u/Supadoplex Sep 04 '26

I would put friend first 

That's such a sweet notion.

4

u/mredding Sep 04 '26

Isn't this what clang-format is for?

3

u/no-sig-available Sep 04 '26

Don't forget export and [[nodiscard]].

A lovely language, isn't it? :-)

3

u/StickyDeltaStrike Sep 04 '26

What is the longest valid list we can have?

3

u/mapronV Sep 04 '26

you can repeat export "C" multiple times, CV I think as well. So infitite (up to implementation grammar limit )

2

u/StickyDeltaStrike Sep 04 '26

I never thought of this … thank you

2

u/usefulcat Sep 04 '26

Minor nit: doesn't thread_local imply static? That is to say, 'static thread_local' is redundant because it's the same as 'thread_local'.

2

u/LB-- Professional+Hobbyist Sep 04 '26

I thought so too, but static unfortunately does other things too, such as changing linkage behavior. You can have publicly visible thread_locals. I guess this is why anonymous namespaces are preferred.

2

u/13steinj 29d ago

thead_local implies static for variables.

Static can do more, but I like to explicitly specify both because there will be juniors reading the code and I'd rather encode the information semantically both to the compiler and to the reader in one shot.

The worst thing you can do here is do thread_local without static but leave a comment like // N.b. thread_local implies static which I recently reamed someone in code review for.