How can I emulate destructuring in C++?

C++C++17DestructuringLanguage Construct

C++ Problem Overview


In JavaScript ES6, there is a language feature known as destructuring. It exists across many other languages as well.

In JavaScript ES6, it looks like this:

var animal = {
    species: 'dog',
    weight: 23,
    sound: 'woof'
}

//Destructuring
var {species, sound} = animal

//The dog says woof!
console.log('The ' + species + ' says ' + sound + '!')

What can I do in C++ to get a similar syntax and emulate this kind of functionality?

C++ Solutions


Solution 1 - C++

In C++17 this is called structured bindings, which allows for the following:

struct animal {
    std::string species;
    int weight;
    std::string sound;
};

int main()
{
  auto pluto = animal { "dog", 23, "woof" };

  auto [ species, weight, sound ] = pluto;

  std::cout << "species=" << species << " weight=" << weight << " sound=" << sound << "\n";
}

Solution 2 - C++

For the specific case of std::tuple (or std::pair) objects, C++ offers the std::tie function which looks similar:

std::tuple<int, bool, double> my_obj {1, false, 2.0};
// later on...
int x;
bool y;
double z;
std::tie(x, y, z) = my_obj;
// or, if we don't want all the contents:
std::tie(std::ignore, y, std::ignore) = my_obj;

I am not aware of an approach to the notation exactly as you present it.

Solution 3 - C++

Mostly there with std::map and std::tie:

#include <iostream>
#include <tuple>
#include <map>
using namespace std;

// an abstact object consisting of key-value pairs
struct thing
{
	std::map<std::string, std::string> kv;
};


int main()
{
	thing animal;
	animal.kv["species"] = "dog";
	animal.kv["sound"] = "woof";

	auto species = std::tie(animal.kv["species"], animal.kv["sound"]);
	
	std::cout << "The " << std::get<0>(species) << " says " << std::get<1>(species) << '\n';
	
	return 0;
}

Solution 4 - C++

I am afraid you cannot have it the way you are used to in JavaScript (which by the way seems to be new technology in JS). The reason is that in C++ you simply cannot assign to multiple variables within a structure/object/assignment expression as you did in

var {species, sound} = animal

and then use species and sound as simple variables. Currently C++ simply does not have that feature.

You could assign to structures and/or objects whilst overloading their assignment operator, but I don't see a way how you could emulate that exact behaviour (as of today). Consider the other answers offering similar solutions; maybe that works for your requirement.

Solution 5 - C++

Another possibility could be done as

#define DESTRUCTURE2(var1, var2, object) var1(object.var1), var2(object.var2)

which would be used like:

struct Example
{
    int foo;
    int bar;
};

Example testObject;

int DESTRUCTURE2(foo, bar, testObject);

yielding local variables of foo and bar.

Of course it's limited to creating variables all of the same type, although I suppose you could use auto to get around that.

And that macro is limited to doing exactly two variables. So you would have to create DESTRUCTURE3, DESTRUCTURE4, and so on to cover as many as you want.

I don't personally like the code style this ends up with, but it comes reasonably close to some of the aspects of the JavaScript feature.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTrevor HickeyView Question on Stackoverflow
Solution 1 - C++dalleView Answer on Stackoverflow
Solution 2 - C++EscualoView Answer on Stackoverflow
Solution 3 - C++ChadView Answer on Stackoverflow
Solution 4 - C++ElyView Answer on Stackoverflow
Solution 5 - C++TheUndeadFishView Answer on Stackoverflow