Skip to content

Commit 22c2ac4

Browse files
committed
fx: Variant load failing when nth item is > 0
Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
1 parent 92dedb0 commit 22c2ac4

2 files changed

Lines changed: 39 additions & 57 deletions

File tree

include/cmcpp/variant.hpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
#define CMCPP_VARIANT_HPP
33

44
#include "context.hpp"
5-
#include "integer.hpp"
6-
#include "float.hpp"
75
#include "store.hpp"
86
#include "load.hpp"
97
#include "util.hpp"
@@ -16,28 +14,26 @@ namespace cmcpp
1614
{
1715
namespace variant
1816
{
19-
template <Variant V>
20-
struct LoadVisitor
21-
{
22-
const CallContext &cx;
23-
V &variant;
24-
size_t index_to_set;
25-
size_t current_index;
26-
int ptr;
17+
template <size_t N, Variant T>
18+
using variantT = typename std::variant_alternative<N, T>::type;
2719

28-
LoadVisitor(const CallContext &cx, V &var, size_t idx, uint32_t ptr)
29-
: cx(cx), variant(var), index_to_set(idx), current_index(0), ptr(ptr) {}
20+
template <Variant T>
21+
void setNthValue(T &var, size_t case_index, const CallContext &cx, uint32_t ptr)
22+
{
23+
constexpr size_t variantSize = std::variant_size<T>::value;
3024

31-
template <typename T>
32-
void operator()(T &)
25+
if (case_index >= variantSize)
3326
{
34-
if (current_index == index_to_set)
35-
{
36-
variant = load<T>(cx, ptr);
37-
}
38-
++current_index;
27+
throw std::out_of_range("Invalid case_index for variant");
3928
}
40-
};
29+
30+
auto setter = [&]<size_t... Indices>(std::index_sequence<Indices...>)
31+
{
32+
((case_index == Indices ? (var = load<variantT<Indices, T>>(cx, ptr), true) : false) || ...);
33+
};
34+
35+
setter(std::make_index_sequence<variantSize>{});
36+
}
4137

4238
template <Variant T>
4339
T load(const CallContext &cx, uint32_t ptr)
@@ -48,8 +44,7 @@ namespace cmcpp
4844
ptr += disc_size;
4945
trap_if(cx, case_index >= std::variant_size_v<T>);
5046
ptr = align_to(ptr, ValTrait<T>::max_case_alignment);
51-
LoadVisitor<T> visitor(cx, retVal, case_index, ptr);
52-
std::visit(visitor, retVal);
47+
setNthValue(retVal, case_index, cx, ptr);
5348
return retVal;
5449
}
5550

test/main.cpp

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -543,45 +543,32 @@ TEST_CASE("Variant")
543543
CHECK(variants == v55);
544544

545545
using VariantList2 = list_t<variant_t<string_t>>;
546-
VariantList2 variants2 = {"Hello World1"};
546+
VariantList2 variants2 = {"Hello World 1", "Hello World 2", "Hello World 3"};
547547
auto vv6 = lower_flat(*cx, variants2);
548548
auto v66 = lift_flat<VariantList2>(*cx, vv6);
549549
CHECK(variants2 == v66);
550550

551-
// using VariantList3 = list_t<variant_t<string_t, uint32_t>>;
552-
// VariantList3 variants3 = {"Hello World2", (uint32_t)42};
553-
// auto vv7 = lower_flat(*cx, variants3);
554-
// auto v77 = lift_flat<VariantList3>(*cx, vv7);
555-
// auto d1 = std::get<string_t>(v77[0]);
556-
// auto d2v = v77[1];
557-
// auto d2 = std::get<uint32_t>(d2v);
558-
// CHECK(variants3 == v77);
559-
560-
// using VariantList4 = list_t<variant_t<string_t, uint32_t, bool_t>>;
561-
// VariantList4 variants4 = {"Hello World3", (uint32_t)42, true};
562-
// auto vv8 = lower_flat(*cx, variants4);
563-
// auto v88 = lift_flat<VariantList4>(*cx, vv8);
564-
// CHECK(variants4 == v88);
565-
566-
// using VariantList3 = list_t<variant_t<string_t, uint32_t>>;
567-
// VariantList3 variants3 = {"Hello World2", (uint32_t)42};
568-
// auto vv7 = lower_flat(*cx, variants3);
569-
// auto v77 = lift_flat<VariantList3>(*cx, vv7);
570-
// auto d1 = std::get<string_t>(v77[0]);
571-
// auto d2v = v77[1];
572-
// auto d2 = std::get<uint32_t>(d2v);
573-
// CHECK(variants3 == v77);
574-
575-
// using VariantList = list_t<variant_t<bool_t>>;
576-
// VariantList variants = {true, false};
577-
// auto vv5 = lower_flat(*cx, variants);
578-
// auto v55 = lift_flat<VariantList>(*cx, vv5);
579-
// CHECK(variants.size() == v55.size());
580-
// auto v0_ = std::get<bool_t>(v55[0]);
581-
// auto v1_ = std::get<bool_t>(v55[1]);
582-
// CHECK(variants[0] == v55[0]);
583-
// CHECK(variants[1] == v55[1]);
584-
// CHECK(variants == v55);
551+
using VariantList3 = list_t<variant_t<string_t, bool_t>>;
552+
VariantList3 variants3 = {"Hello World 1", "Hello World 2", "Hello World 3"};
553+
auto vv7 = lower_flat(*cx, variants3);
554+
auto v77 = lift_flat<VariantList3>(*cx, vv7);
555+
CHECK(variants3 == v77);
556+
557+
VariantList3 variants3b = {true, false, true};
558+
auto vv7b = lower_flat(*cx, variants3b);
559+
auto v77b = lift_flat<VariantList3>(*cx, vv7b);
560+
CHECK(variants3b == v77b);
561+
562+
VariantList3 variants3c = {true, "false", true, "Hello World 1", "Hello World 2", "Hello World 3"};
563+
auto vv7c = lower_flat(*cx, variants3b);
564+
auto v77c = lift_flat<VariantList3>(*cx, vv7c);
565+
CHECK(variants3b == v77c);
566+
567+
using VariantList4 = list_t<variant_t<string_t, uint32_t, bool_t>>;
568+
VariantList4 variants4 = {"Hello World3", (uint32_t)42, true};
569+
auto vv8 = lower_flat(*cx, variants4);
570+
auto v88 = lift_flat<VariantList4>(*cx, vv8);
571+
CHECK(variants4 == v88);
585572
}
586573

587574
TEST_CASE("Option")

0 commit comments

Comments
 (0)