// structBind.cpp — Phase 2.7 cxxSmoke check 4. // // Exercises C++17 structured bindings. Two flavours: // (a) direct binding of a plain aggregate (the "structured-binding-by- // element" form — no tuple_size/get<> machinery needed). // (b) tuple-style binding of a user type that opts in via std::tuple_size, // std::tuple_element, and a get() free function. This is the // customisation point that std::tie / std::pair / std::tuple all use. // // $025000 = 0x0007 (aggregate first member) // $025002 = 0x002A (aggregate second member) // $025004 = 0x00DE (tuple-protocol member 0) // $025006 = 0x00AD (tuple-protocol member 1) // $025008 = 0x0099 success marker #include #include // We have no host libc++, so std::tuple_size / std::tuple_element are not // declared anywhere by default. Provide the primary class templates so // the user-type specialisation below has something to specialise (and so // clang's structured-binding lookup finds them). namespace std { template struct tuple_size; template struct tuple_element; } // Aggregate destructured by element (no protocol). struct Pair { uint16_t a; uint16_t b; }; // User type opting in to the tuple protocol for structured bindings. struct Pt { uint16_t x; uint16_t y; }; template uint16_t get(const Pt &p) { if constexpr (I == 0) { return p.x; } else { return p.y; } } namespace std { template <> struct tuple_size { static constexpr size_t value = 2; }; template <> struct tuple_element<0, Pt> { using type = uint16_t; }; template <> struct tuple_element<1, Pt> { using type = uint16_t; }; } int main(void) { Pair p = { 0x0007, 0x002A }; auto [pa, pb] = p; *(volatile uint16_t *)0x025000UL = pa; *(volatile uint16_t *)0x025002UL = pb; Pt q = { 0x00DE, 0x00AD }; auto [qx, qy] = q; *(volatile uint16_t *)0x025004UL = qx; *(volatile uint16_t *)0x025006UL = qy; *(volatile uint16_t *)0x025008UL = 0x0099; return 0; }