73 lines
2.1 KiB
C++
73 lines
2.1 KiB
C++
// 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<I>() 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 <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
|
|
// 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 <typename T> struct tuple_size;
|
|
template <size_t I, typename T> 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 <size_t I>
|
|
uint16_t get(const Pt &p) {
|
|
if constexpr (I == 0) {
|
|
return p.x;
|
|
} else {
|
|
return p.y;
|
|
}
|
|
}
|
|
|
|
|
|
namespace std {
|
|
template <> struct tuple_size<Pt> { 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;
|
|
}
|