diff --git a/include/revng/ADT/STLExtras.h b/include/revng/ADT/STLExtras.h index 233bbca25..4f716ff3b 100644 --- a/include/revng/ADT/STLExtras.h +++ b/include/revng/ADT/STLExtras.h @@ -4,10 +4,13 @@ // This file is distributed under the MIT License. See LICENSE.md for details. // +#include #include #include "llvm/ADT/STLExtras.h" +#include "revng/Support/Concepts.h" + // // is_integral // @@ -37,15 +40,54 @@ static_assert(is_specialization_v, std::pair>); // HasTupleSize // -template +template concept HasTupleSize = requires { - std::tuple_size::value; + typename std::tuple_size::type; + { std::tuple_size_v } -> convertible_to; }; static_assert(HasTupleSize>); static_assert(!HasTupleSize>); static_assert(!HasTupleSize); +// +// IsTupleLike +// + +namespace detail { + +template +concept HasTupleElement = requires(T Value) { + typename std::tuple_element_t>; + { get(Value) } -> convertible_to &>; +}; + +template +constexpr auto checkTupleElementTypes(std::index_sequence) { + return (HasTupleElement && ...); +} + +template +constexpr auto checkAllTupleElementTypes() { + auto Sequence = std::make_index_sequence>(); + return checkTupleElementTypes(Sequence); +} + +} // namespace detail + +// clang-format off +template +concept IsTupleLike = (not std::is_reference_v + and HasTupleSize + and detail::checkAllTupleElementTypes()); +// clang-format on + +static_assert(IsTupleLike>); +static_assert(IsTupleLike>); +static_assert(IsTupleLike>); +static_assert(IsTupleLike>); +static_assert(not IsTupleLike); + //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// diff --git a/tests/unit/Model.cpp b/tests/unit/Model.cpp index b448bae2f..2a72e5e2e 100644 --- a/tests/unit/Model.cpp +++ b/tests/unit/Model.cpp @@ -180,6 +180,8 @@ public: INTROSPECTION_NS(TestTupleTree, Root, Elements) +static_assert(IsTupleLike); + BOOST_AUTO_TEST_CASE(TestTupleTreeReference) { using namespace TestTupleTree;