Update: This article is more than a year old. Recent versions of macOS ship with much better C++17 support out of the box, so you should check whether your default Clang already supports your use case before bothering with this approach.
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.
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.
If you want to try out some new features today, you have a few options:
std::experimentalto play with certain features
- Install a more modern llvm
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.