How can I emulate destructuring in C++?

14,773

Solution 1

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 2

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 3

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

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

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.

Share:
14,773
Trevor Hickey
Author by

Trevor Hickey

and programming

Updated on June 24, 2022

Comments

  • Trevor Hickey
    Trevor Hickey about 2 years

    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?