std::optional -> Yak Shaving

All I wanted to do was use std::optional. There is a common pattern in computation where you call a function and the function can either return a value or fail. There are various patterns to handle this most of which are pretty ugly.

You can use exceptions, where you raise an exception in a function and leave it to the caller to trap that exception and so on and so forth all the way up the call stack.

You can return a sentinel value – a special, obviously wrong value – which you handle specially. I would advise against this because it’s often unclear how “special” or “obvious” or “wrong” that value actually is. I’ve been burned by -1, by None, and even -Inf and +Inf. Basically what happens is over time you forget that sentinel value and it causes the nastiest bugs you can imagine. Just. Do. Not. Do. This.

In C/C++ you can pass in a boolean “ok” variable that is set by the function. I feel a little yucky doing that because it’s one of those surprising things you find in your code. Not only is the code returning a value – which you immediately focus on – but it’s also setting a parameter you pass in – which you may not notice.

Cool languages sometimes have neat ways of handling things when a function errors out. Haskell has maybe which lets you declare that a value may be invalid and you can write your functions to handle the case where an input value is invalid and the code looks compact and neat and the intent is very clear.

So I jumped out of my chair when I learned about std::optional. This allows you to, efficiently, return a value which can be set to be “nothing” or “something”. If there is nothing in it a truth test returns false otherwise a truth test will return true. A maybe in C++ !? Is that like the boss wearing a Hawaiian shirt on Hawaiian shirt day? I wanted to find out.

So I eagerly wrote up my code using std::optional. This is a C++17 feature and on my mac – which was Sierra – Apple’s default compiler did not seem to support this. (I found out later that copying some library files can do the trick).

So, I did the usual web-search and discovered this well done post with directions on how to install the latest clang compiler via homebrew.

During the install, homebrew, after chewing on things for a long time, spit out the following unsatisfactory message.

CMake Warning at tools/xcode-toolchain/CMakeLists.txt:60 (message):
  Failed to detect the version of an installed copy of Xcode, falling back to
  highest supported version.  Set XCODE_VERSION to override.


CMake Error at tools/xcode-toolchain/CMakeLists.txt:80 (message):
  Could not identify toolchain dir

After another chase around the internet it turned out that, this particular formula, which needs to compile the compiler, for whatever reason, can’t work with just the command line tools installs. It needs Apples XCode.app IDE installed. I don’t use XCode – I have my own preferred IDE and I use CMake so I had so far saved about 5GB of disk space by not having Xcode.app just sitting there doing nothing.

I sighed and went to the App Store, found XCode and clicked “Get” and then “Install”. “Xcode can only be installed on macOS High Sierra, you have Sierra” said my computer. I sat there and blinked for a few seconds.

I sighed and squared my shoulders. I closed all my browser tabs. There goes my things to read, there goes my list of things to do. Yes, I can probably reopen all the tabs on the other side, but let’s face it, sometimes you gotta declare task bankruptcy and start all over again “Oh, I didn’t send in that report? Sorry, can you send the link again please, I’ll do it tonight…”

Well, 40 minutes later Sierra had upgraded to High Sierra. Then I installed XCode. I lost track of how long that took – maybe 10 minuites. Bye bye 5GB disk space. Then I ran brew install again. 120 minutes later clang-6.0 finished bootstrapping and a quick call to make, after changing the CMakeLists.txt confirms I have all I need to compile C++ code with std::optional.

Well, I guess now I can finish my study of std::optional. Woops. It’s bedtime. I guess I’ll have to do it tomorrow …

I have no doubt all my friends will have advice on how I could have done it in a much simpler way, and all I have to say to them, is where were you when I needed you?
toonvectors-158618-140

Epilogue

std::optional is pretty smooth in usage. Your function parameter and return types have to be declared as std::optional and you just have to remember that std::optional looks like a pointer to T, so you do T->x, T->y and so on but other wise there are nice creature comforts: to return nothing, you just do return {} and to return the value, you just do return T, the compiler takes care of converting things to the optional type.

Epilogue II

As a final yap from that yak, upgrading the tool chain upgraded clang-format to version 6.0 from 5.0 and which led me to discover that the style format option ‘SplitEmptyFunctionBody’ doesn’t exist in 6.0 onwards. Oh the joys …

Advertisements

4 Replies to “std::optional -> Yak Shaving”

  1. There’s also a proposal[1] in the review process related to `std::expected`, which would be Rust’s `std::Result` equivalent for C++. It’s similar to `std::optional`, but allows to return “something or something else”, and this would be very handy in returning error state from a function. So i.e. `expected` would return a string, or an integer error value.

    [1] – https://issues.isocpp.org/show_bug.cgi?id=29

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s