|
21 | 21 | // NN is large enough to hold the #alternatives in the union)
|
22 | 22 | //
|
23 | 23 | // For an object U of union type that
|
24 |
| -// has a unique address, when inject a call to this (zero-based alternative #s) |
| 24 | +// has a unique address, when Inject a call to this (zero-based alternative #s) |
25 | 25 | //
|
26 | 26 | // U is created initialized on_set_alternative(&U,0) = the first alternative# is active
|
27 | 27 | //
|
28 | 28 | // U is created uninitialized on_set_alternative(&U,invalid)
|
29 | 29 | //
|
30 |
| -// U.A = xxx (alt #A is assigned to) on_set_alternative(&U,#A) |
| 30 | +// U.A = xxx (alt A is assigned to) on_set_alternative(&U,#A) |
31 | 31 | //
|
32 |
| -// U.A (alt #A is otherwise mentioned) on_get_alternative(&U,#A) |
| 32 | +// U.A is passed to a function by on_set_alternative(&U,unknown) |
| 33 | +// pointer/reference to non-const |
| 34 | +// |
| 35 | +// U.A (alt A is otherwise used) on_get_alternative(&U,#A) |
33 | 36 | // and A is not a common initial
|
34 | 37 | // sequence
|
35 | 38 | //
|
|
44 | 47 | // std::cout << t.b; union_registry<>::on_get_alternative(&u,1);
|
45 | 48 | // } union_registry<>::on_destroy(&u);
|
46 | 49 | //
|
47 |
| -// For all unions with under 256 alternatives, use union_registry<> |
48 |
| -// For all unions with between 256 and 16k alternatives, use union_registry<uint16_t> |
49 |
| -// If you find a union with >16k alternatives, email me the story and use union_registry<uint32_t> |
| 50 | +// For all unions with up to 254 alternatives, use union_registry<> |
| 51 | +// For all unions with between 255 and 16k-2 alternatives, use union_registry<uint16_t> |
| 52 | +// If you find a union with >16k-2 alternatives, email me the story and use union_registry<uint32_t> |
50 | 53 | //
|
51 | 54 | template<typename Tag = uint8_t>
|
52 | 55 | class union_registry {
|
53 | 56 | inline static auto tags = extrinsic_storage<Tag>{};
|
54 | 57 | inline static auto log = std::ofstream{ "union-violations.log" };
|
55 | 58 | public:
|
56 | 59 | inline static auto invalid = std::numeric_limits<Tag>::max();
|
| 60 | + inline static auto unknown = std::numeric_limits<Tag>::max()-1; |
57 | 61 |
|
58 | 62 | static auto on_destroy (void* pobj) -> void { tags.erase(pobj); }
|
59 | 63 | static auto on_set_alternative(void* pobj, uint32_t alt) -> void { tags[pobj] = alt; }
|
60 | 64 | static auto on_get_alternative(void* pobj, uint32_t alt, std::source_location where = std::source_location::current()) -> void
|
61 | 65 | {
|
62 | 66 | if (auto active = tags[pobj];
|
63 | 67 | active != alt
|
64 |
| - ) { |
| 68 | + && active != unknown |
| 69 | + ) |
| 70 | + { |
65 | 71 | log << where.file_name() << '(' << where.line() << ") " << where.function_name()
|
66 | 72 | << ": union " << pobj
|
67 | 73 | << ", active " << (active == invalid ? "invalid" : std::to_string(active))
|
|
0 commit comments