/* * Copyright (C) 2018 ScyllaDB */ /* * This file is part of Scylla. * * Scylla is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Scylla is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scylla. If not, see . */ #pragma once namespace meta { // Wrappers that allows returning a list of types. All helpers defined in this // file accept both unpacked and packed lists of types. template struct list { }; namespace internal { template constexpr ssize_t do_find_if_unpacked() { ssize_t i = -1; ssize_t j = 0; (..., ((Vs && i == -1) ? i = j : j++)); return i; } template struct negative_to_empty : std::integral_constant { }; template<> struct negative_to_empty<-1> { }; template struct is_same_as { template using type = std::is_same; }; template typename Predicate, typename... Ts> struct do_find_if : internal::negative_to_empty::value...>()> { }; template typename Predicate, typename... Ts> struct do_find_if> : internal::negative_to_empty::value...>()> { }; } // Returns the index of the first type in the list of types list of types Ts for // which Predicate typename Predicate, typename... Ts> constexpr size_t find_if = internal::do_find_if::value; // Returns the index of the first occurrence of type T in the list of types Ts. template constexpr size_t find = find_if::template type, Ts...>; namespace internal { template struct do_get_unpacked { }; template struct do_get_unpacked : do_get_unpacked { }; template struct do_get_unpacked<0, T, Ts...> { using type = T; }; template struct do_get : do_get_unpacked { }; template struct do_get> : do_get_unpacked { }; } // Returns the Nth type in the provided list of types. template using get = typename internal::do_get::type; namespace internal { template struct do_take_unpacked { }; template struct do_take_unpacked<0, list> { using type = list; }; template struct do_take_unpacked<0, list, U, Us...> { using type = list; }; template struct do_take_unpacked, U, Us...> { using type = typename do_take_unpacked, Us...>::type; }; template struct do_take : do_take_unpacked { }; template struct do_take> : do_take_unpacked { }; } // Returns a list containing N first elements of the provided list of types. template using take = typename internal::do_take, Ts...>::type; namespace internal { template struct do_for_each_unpacked { template static constexpr void run(Function&& fn) { (..., fn(static_cast(nullptr))); } }; template struct do_for_each : do_for_each_unpacked { }; template struct do_for_each> : do_for_each_unpacked { }; } // Executes the provided function for each element in the provided list of // types. For each type T the Function is called with an argument of type T*. template constexpr void for_each(Function&& fn) { internal::do_for_each::run(std::forward(fn)); }; namespace internal { template struct get_size : std::integral_constant { }; template struct get_size> : std::integral_constant { }; } // Returns the size of a list of types. template constexpr size_t size = internal::get_size::value; template