/* * Copyright (c) 2020, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include namespace AK { template struct TypeList; template struct TypeListElement; #if __has_builtin(__type_pack_element) template struct TypeListElement> { using Type = __type_pack_element; }; #else template struct TypeListElement> : TypeListElement> { }; template struct TypeListElement<0, TypeList> { using Type = Head; }; #endif template struct TypeList { static constexpr unsigned size = sizeof...(Types); template using Type = typename TypeListElement>::Type; }; template struct TypeWrapper { using Type = T; }; template constexpr void for_each_type_impl(F&& f, IndexSequence) { (forward(f)(TypeWrapper> {}), ...); } template constexpr void for_each_type(F&& f) { for_each_type_impl(forward(f), MakeIndexSequence {}); } template constexpr void for_each_type_zipped_impl(F&& f, IndexSequence) { (forward(f)(TypeWrapper> {}, TypeWrapper> {}), ...); } template constexpr void for_each_type_zipped(F&& f) { static_assert(ListA::size == ListB::size, "Can't zip TypeLists that aren't the same size!"); for_each_type_zipped_impl(forward(f), MakeIndexSequence {}); } } #if USING_AK_GLOBALLY using AK::for_each_type; using AK::for_each_type_zipped; using AK::TypeList; using AK::TypeListElement; using AK::TypeWrapper; #endif