|
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