diff --git a/include/iris/x4/core/detail/parse_into_container.hpp b/include/iris/x4/core/detail/parse_into_container.hpp index ac90a9a5a..8a40b2493 100644 --- a/include/iris/x4/core/detail/parse_into_container.hpp +++ b/include/iris/x4/core/detail/parse_into_container.hpp @@ -212,7 +212,19 @@ parse_into_container( "`unused_type` should not be passed to `parse_into_container`. Use `x4::assume_container(attr)`" ); - return parse_into_container_impl::call(parser, first, last, ctx, attr); + if constexpr (traits::is_variant_v) { + // e.g. `char` when the caller is `+char_` + using attribute_type = parser_traits::attribute_type; + + // e.g. `std::string` when the attribute_type is `char` + using substitute_type = traits::variant_find_substitute_t>; + + // instead of creating a temporary `substitute_type`, append directly into the emplaced alternative + auto& variant_alt = attr.template emplace(); + return parse_into_container_impl::call(parser, first, last, ctx, variant_alt); + } else { + return parse_into_container_impl::call(parser, first, last, ctx, attr); + } } } // iris::x4::detail diff --git a/test/x4/alternative.cpp b/test/x4/alternative.cpp index bb0db2d74..bd432b9f7 100644 --- a/test/x4/alternative.cpp +++ b/test/x4/alternative.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,7 @@ TEST_CASE("alternative") using x4::unused; using x4::omit; using x4::eps; + using x4::true_; IRIS_X4_ASSERT_CONSTEXPR_CTORS(char_ | char_); @@ -220,7 +222,37 @@ TEST_CASE("alternative") (void)line; } - // single-element tuple tests + // attribute is a variant containing container + { + constexpr auto parser = +true_; + using Parser = std::remove_const_t; + using Attr = iris::rvariant>; + + using attribute_type = x4::parser_traits::attribute_type; + STATIC_CHECK(std::same_as>); + + using substitute_type = x4::traits::variant_find_substitute_t; + STATIC_CHECK(std::same_as>); + + Attr var; + REQUIRE(parse("truetrue", parser, var)); + } + { + constexpr auto parser = +char_; + using Parser = std::remove_const_t; + using Attr = iris::rvariant; + + using attribute_type = x4::parser_traits::attribute_type; + STATIC_CHECK(std::same_as); + + using substitute_type = x4::traits::variant_find_substitute_t; + STATIC_CHECK(std::same_as); + + Attr var; + REQUIRE(parse("123", parser, var)); + } + + // single element tuple-like case { alloy::tuple> fv; REQUIRE(parse("12345", int_ | +char_, fv));