If you are willing to return std::optional, clang-tidy has a (static) control flow sensitive check that enforces you check to see the value is valid before unwrapping. https://clang.llvm.org/extra/clang-tidy/checks/bugprone/unch...

This would prevent the last bug (!ua()) as the control flow sensitive analysis can reason about both branches: that it is invalid to deref ua within the block. The dynamic check misses the bug because the branch is never taken for the given inputs.

I am fairly confident that the clang-tidy pass is simpler and more precise in most cases than the hand-rolled implementation. (That said the static check may not be able to reason about mutation well.)

If you need to pass an error in the failure case, you can use std::expected (available in C++23). clang-tidy has an open bug about supporting a similar check for std::expected: https://github.com/llvm/llvm-project/issues/135045

Funny if only marginally related fact: even though neither the C++11 syntax

  if (int x = foo(); x) { ... }
nor the C++98 syntax

  if (int x = foo()) { ... }
is supported in C99, it still introduces the rule that the entire if statement is a scope (which it wasn’t in C89). So as a party trick, here’s a way to check for C99 without using the preprocessor:

  int c99() {
      enum { C99 = 1 };
      {
          if (sizeof(enum { C99 = 0 })) { }
          return C99;
      }
  }
I make no promises about the behaviour of this code on insufficiently anal compilers like TCC.

This is very cool, although a more compact way to check for single line comments (introduced in C99) versus division using "//* */". I used that trick here:

https://github.com/ioccc-src/winner/blob/a1c86c8a7a533e3c2cd...

You gave an IOCCC snippet as an example of a C99 coding trick you know? I mean, the code looks visually cool, but it's funny to explain a code concept using code shaped like an anime character. (At least that's what I think it is.)

I don't know how to link to just a specific part of the line, but the interesting bit is at the end of line 16 and the start of line 17:

    x*=02//* */2
          -1;
With C89, this is evaluated as "x *= 02 / 2 - 1", or "x *= 0".

With C99, this is evaluated as "x *= 02 / -1", or "x *= -2".

> I make no promises about the behaviour of this code on insufficiently anal compilers like TCC.

But tcc isn't a C++ compiler at all?

[deleted]

tcc version 0.9.28rc returns "1", whatever that means.

Pretty sure that means that tcc at least believes it is a C99 (or later) compiler; if it conformed to an earlier spec it (probably?) would have considered the inner `enum { C99 = 0 }` definition to be still in scope, and the return value would be 0.

I think.

That’s correct. I did check before posting that TCC 0.9.27 on Godbolt returned zero here, but I didn’t look beyond that. Evidently things have changed since that release.

Isn't that what git tags are for? Just create a tag with something human-readable like, I dunno, a version number would be good. And that way ANYONE can see the state of your sources for a given build.

If you use github release workflow, you don't even have a choice about it. You cannot create a release without creating a matching tag.

Yeah that would be free if you have all the CI stuff set up.

Maybe she doesn't, though. At a previous job I logged build IDs and never ended up needing them because we were able to uphold a Git-first process pretty well

I think there's an easy compromise with `git describe`. `git describe` gives you a mix of tags and commit information to easily describe every commit to a build tool, but not need to setup a "CI tagger". If the commit has (an annotated) tag, `git describe` returns the tag name. If the commit isn't directly tagged, it returns `{nearesttag}-{commit count after that tag}-g{prefix of commit hash}`. Such as `v1.2.3-4-g01abcd`.

You can pass a `git describe` directly to just about any git command that takes a "commitish", so can copy and paste it directly to `git switch` or `git checkout` just as you would with a full hash. Except you also have prefixed human-readable version information that you can update.

About the only complaint with `git describe` is that if you are presenting these version numbers in semver scenarios and want the best semver ordering you want to replace that first "-" with a "+" and the second "-" with a ".", which aligns it better with semver's optional build metadata rather than looking like a semver pre-release.

Keep in mind that with U+258x characters you get a unique paired set by just inverting the foreground and background. This does work with some, but not all, of the U+259x characters as well.

You may very well be able to ditch colors using this technique with additional characters. Many characters are distinct with their inverted counterpart.