Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why structured bindings only work with auto

Structured bindings have been introduced with c++17. They give the ability to declare multiple variables initialised from a tuple or struct.

This code compiles using a c++17 compiler.

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 1);

    auto [ d, i ] = tuple;

    std::cout << "d=" << d << " i=" << i <<  '\n';

    return 0;
}

If I don't declare the variables with auto I get the error

error: expected body of lambda expression [d2 , i2] = tuple;

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 2);

    double d2;
    int i2;

    [d2 , i2] = tuple;

    return 0;
}

I used clang version 4.0.0 and the compile option -std=c++1z.

Can I assign existing variables to a structured binding? Do I need to use auto?

like image 351
schorsch312 Avatar asked Oct 16 '17 07:10

schorsch312


2 Answers

The error message your got is pretty indicative of why it's only allowed with auto: lack of ambiguity that will make the grammar even more context dependent.

A pair of square brackets at the start of an expression indicates a lambda. What you are asking is for the standard to specify that sometimes [d2 , i2] is the beginning of a lambda that captures d2 and i2 by value, and at other times it's an unpacking assignment. All based on what follows it.

It's just not worth the complexity to add it to the language. Especially, since as Some programmer dude noted, you already have std::tie to do what you want with tuples.

Not only that, std::tie allows you to ignore some of the unpacked values, something structured bindings don't support yet. So it all boils down to having a more limited form of syntactic sugar, to do something the standard library already does with tuples.


Oh, and if you are disgruntles that std::tie works only with tuples, you can expand it to work with any POD yourself. Just look at this magic_get implementation. One can apply the same idea to constexpr transform a POD into a tuple of reference that can be fed to std::tie. Something like this:

std::tie(d2, i2) = magic_unpack(/*some POD that isn't a tuple*/);
like image 157
StoryTeller - Unslander Monica Avatar answered Oct 07 '22 09:10

StoryTeller - Unslander Monica


Also, you can using std::tie() to unpack the tuple into its individual components. Such as

#include <iostream>
#include <tuple>

int main() {
    auto tuple = std::make_tuple(1.0, 1);
    double d2;
    int i2;
    std::tie(d2, i2) = tuple;

    std::cout << "d2=" << d2 << " i2=" << i2 <<  '\n';

    return 0;
}
like image 23
msc Avatar answered Oct 07 '22 08:10

msc