Trying out C++17 on macOS

C++17 brings a lot of cool new features. Viva64 have a nice overview. Sadly, they can’t all be used out of the box on macOS, as the default toolchain isn’t very modern.

The problem

Apple installs their own version of llvm along with Xcode. This custom llvm also uses custom version numbers, so it isn’t always easy to know which version of mainline llvm it is based on. For instance on my macOS High Sierra, I get:

$ clang --version
Apple LLVM version 9.0.0 (clang-900.0.39.2)

This version number has nothing to with the official llvm version, which is currently at 6.0.0. All I know is that it is behind.

The solution(s)

If you want to try out some new features today, you have a few options:

  • Use std::experimental to play with certain features
  • Install a more modern llvm

Using std::experimental

Sometimes, the C++ standards committee publishes experimental C++ language and library extensions for future standardization. These go in the std::experimental namespace. If you just want to play with some new features, your toolchain might already include what you’re looking for here. However, be aware that these features as they exist in the experimental namespace are not guaranteed to be identical to how they end/ended up in the actual C++ standard! So this should just be used for toying around, not  for production code.

As an example, I wanted to try out the new optional feature. This was included in a technical specification, and has been available as std::experimental::optional for a while. Note however that its interface changed before being merged to the official standard as std::optional. The former for instance lacks the has_value member function.

Installing a more modern llvm

This is the proper solution. It’s not too hard either! First, you probably don’t want to risk breaking your current Xcode setup by installing a mainline llvm interfering with the Apple llvm used by Xcode. Luckily, homebrew avoids this problem by default, by installing llvm in another location than the Apple llvm, and not adding the new one to path.

Embedded Artistry has a good guide for this. In short, all you need to do is

$ brew install --with-toolchain llvm

This will take quite some time, and you’ll end up with mainline llvm (currently version 6.0.0) in a path you can find by running:

$ brew --prefix llvm

On my machine, I get:


I’m not going to copy paste their entire guide, so I suggest you read through it for the details of how to configure your project to use the newly installed mainline llvm instead of the apple llvm you have in path.

If you enjoyed this post, you can subscribe to my blog, or follow me on Twitter.

Leave a Reply

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

You are commenting using your 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

%d bloggers like this: