C++17: Structured Bindings

This is one of a series of posts on C++17 features – see also previous post on if initialisers.

Structured bindings are a convenient way of handling multiple return values from functions. Whilst F# has been able to do this:

let f() = 42, "Hello, World" // return a pair of values
let a, b = f() // assign a and b to the values returned by f

in C++, we’ve had to declare the variables up front and use std::tie to assign values (so not only does this take more lines, we also have to default initialise the variables then throw away the defaults).

auto t = std::make_tuple( 42, "Hello, World" );
int a, b;
std::tie( a, b ) = t;

The new structured bindings are much more concise, even if the use of square brackets came as a surprise. Even better, you can use structured bindings with structs and std::array.

int my_int{ 42 };
std::string my_string{ "Hello, World" };
bool my_bool{ true };

auto return_pair()
{
    return std::make_pair( my_int, my_string );
}

auto return_tuple()
{
    return std::make_tuple( my_int, my_string, my_bool );
}

struct MyStruct
{
    int a;
    double b;
    int c;
    
    static MyStruct Expected;
};

MyStruct MyStruct::Expected = { 1, 2.2, 3 };

auto return_struct()
{
    return MyStruct::Expected;
}

auto return_array()
{
    return std::array<int,3>{ 1, 2, 3 };
}

auto return_map()
{
    return std::map<int, std::string>{ {1, "a"}, {2, "b"}, {3, "c"} };
}

TEST( Cpp17, structured_bindings_for_pair )
{
    auto [i, s] = return_pair();
    
    EXPECT_EQ( my_int, i );
    EXPECT_EQ( my_string, s );
}

TEST( Cpp17, structured_bindings_for_tuple )
{
    auto [i, s, b] = return_tuple();
    
    EXPECT_EQ( my_int, i );
    EXPECT_EQ( my_string, s );
    EXPECT_EQ( my_bool, b );
}

TEST( Cpp17, structured_bindings_for_struct )
{
    auto [i1, d, i2] = return_struct();
    
    EXPECT_EQ( MyStruct::Expected.a, i1 );
    EXPECT_EQ( MyStruct::Expected.b, d );
    EXPECT_EQ( MyStruct::Expected.c, i2 );
}

TEST( Cpp17, structured_bindings_for_array )
{
    auto [i1, i2, i3] = return_array();
    
    EXPECT_EQ( 1, i1 );
    EXPECT_EQ( 2, i2 );
    EXPECT_EQ( 3, i3 );
}

TEST( Cpp17, structured_bindings_for_iterating_over_map )
{
    for ( const auto& [key,value] : return_map() )
    {
        switch (key)
        {
            case 1: EXPECT_EQ( "a", value ); break;
            case 2: EXPECT_EQ( "b", value ); break;
            case 3: EXPECT_EQ( "c", value ); break;
            default: break;            
        };
    }
}

For me, the best examples come when combining features – the range-based for loop with structured bindings is a thing of beauty.

See also next C++17 post.

2 Comments

Filed under C++, C++ Code, Programming

2 responses to “C++17: Structured Bindings

  1. Pingback: C++17: if initialiser | musingstudio

  2. Pingback: C++17: Nested Namespaces | musingstudio

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.