65816-llvm-mos/tests/cxxSmoke/structBind.cpp
Scott Duensing da095402ec Updated
2026-06-02 23:17:57 -05:00

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;
}