Skip to content

Commit

Permalink
Patching up tuple::visit edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
malachib committed Mar 10, 2024
1 parent 6d623f8 commit f9859c6
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 7 deletions.
18 changes: 17 additions & 1 deletion src/estd/internal/variadic/visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct visit_tuple_functor
using type = typename tuple_element<I, Tuple>::const_valref_type;
type v = get<I>(tuple);

return f(variadic::instance<I, T>{v}, std::forward<TArgs>(args)...);
return f(variadic::instance<I, const T>{v}, std::forward<TArgs>(args)...);
}
};

Expand All @@ -72,6 +72,22 @@ struct visitor_instance : in_place_type_t<T>
ESTD_CPP_CONSTEXPR_RET const_pointer operator->() const { return &value; }
};

// string literals like to appear this way. We need a specialization here
// because acquiring pointer to this guy is tricky
template <class T, unsigned N>
struct visitor_instance<T (&)[N]> : in_place_type_t<T (&)[N]>
{
using reference = T (&)[N];

reference value;

constexpr explicit visitor_instance(reference value) : value{value} {}

// NOTE: No arrow operator - pointer is hard to do and arrow wouldn't
// make sense for this type anyway
};


}

namespace experimental {
Expand Down
5 changes: 4 additions & 1 deletion src/estd/streambuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@ class streambuf :
{
static_assert(concepts::v1::impl::OutStreambuf<this_type>, "Must conform to ostreambuf concept");
}
#else
#elif __cpp_constexpr >= 201304L
static constexpr bool verify_istream() { return {}; }
static constexpr bool verify_ostream() { return {}; }
#else
static void verify_istream() {}
static void verify_ostream() {}
#endif

int_type sungetc()
Expand Down
33 changes: 28 additions & 5 deletions test/catch/tuple-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,9 @@ TEST_CASE("tuple")
// FIX: As it should be, this can't convert a temporary to a reference
EmptyClass v1 = estd::get<0>(t);

t.visit([](internal::visitor_instance<EmptyClass> vi)
// DEBT: For empty classes, would be nice to avoid const - though technically
// const is correct here
t.visit([](internal::visitor_instance<const EmptyClass> vi)
{
return false;
});
Expand Down Expand Up @@ -339,20 +341,41 @@ TEST_CASE("tuple")
{
tuple<> v;

#if __cplusplus >= 201402L
v.visit([](auto& v)
{
FAIL();
});
#endif
}
SECTION("const")
{
const tuple<int> v(0);

/*
v.visit([](const auto& v)
#if __cplusplus >= 201402L
int which = v.visit([](const auto& v)
#else
int which = v.visit([](variadic::v3::instance<const int> v)
#endif
{
REQUIRE(v == 0);
}); */
REQUIRE(v.value == 0);
return true;
});

REQUIRE(which == 0);
}
SECTION("array ref")
{
const char (&s)[4] = "hi!";
const tuple<decltype(s)> v(s);

int which = v.visit([](const auto& v)
{
REQUIRE(v.value == "hi!");
return true;
});

REQUIRE(which == 0);
}
}
SECTION("sparse vs non-sparse")
Expand Down

0 comments on commit f9859c6

Please sign in to comment.