/*
* 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 typename Predicate, typename... Ts>
static constexpr const bool all_of = std::conjunction_v...>;
}