Adding C++17 structured bindings support to your classes
This is a very powerful and expressive feature, but the most interesting element for me is the ability to add support for this to your own classes. This post is a short tutorial on how to do this, mostly for my own future reference.
The great news is that structured bindings are supported out-of-the-box for classes where all the non-static member variables are public (or all public-only non-statc members are in a single direct base class). So a class like this can be decomposed with no additional code:
So can this:
If you have more complex classes, or want to wrap/process members before exposing them, you’ll need to add support yourself. Fortunately, this is rather elegantly built on top of existing mechanisms. All you need to do is tell the compiler how many variables you want to expose, the types of them, and how to get at the values. This is done through the
Supporting other classes
For demonstration purposes we’ll write a small class named
Config, which stores some immutable configuration data. We’ll be returning
name as a C++17
id by value, and
data by reference to const.
The simplest specialization is
std::tuple_size. Since there are three elements, we’ll just return
get. We’ll use C++17’s
if constexpr for brevity. I’ve just added this as a member function to avoid the headache of template friends, but you can also have it as a non-member function found through ADL.
Finally we need to specialize
std::tuple_element. For this we just need to return the type corresponding to the index passed in, so
const std::vector<std::string>& for
2. We’ll cheat and get the compiler to work out the types for us using the
get function we wrote above. This way, we don’t need to touch this specialization if we want to change the types we return later, or want to add more variables to the class.
You could do this the long way if you aren’t comfortable with the
With all of that done, we can now decompose
Config like so:
Let me know what you think of this article on twitter @TartanLlama or leave a comment below!