From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- src/include/uses_allocator.h | 266 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 src/include/uses_allocator.h (limited to 'src/include/uses_allocator.h') diff --git a/src/include/uses_allocator.h b/src/include/uses_allocator.h new file mode 100644 index 000000000..35cdbd709 --- /dev/null +++ b/src/include/uses_allocator.h @@ -0,0 +1,266 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +// Derived from: +/* uses_allocator.h -*-C++-*- + * + * Copyright (C) 2016 Pablo Halpern + * Distributed under the Boost Software License - Version 1.0 + */ +// Downloaded from https://github.com/phalpern/uses-allocator.git + +#pragma once + +#include +#include +#include +#include + +namespace ceph { + +namespace internal { +template +T make_from_tuple_imp(Tuple&& t, std::index_sequence) +{ + return T(std::get(std::forward(t))...); +} +} // namespace internal + +template +T make_from_tuple(Tuple&& args_tuple) +{ + using namespace internal; + using Indices = std::make_index_sequence>>; + return make_from_tuple_imp(std::forward(args_tuple), Indices{}); +} + +//////////////////////////////////////////////////////////////////////// + +// Forward declaration +template +auto uses_allocator_construction_args(const Alloc& a, Args&&... args); + +namespace internal { + +template +struct has_allocator : std::uses_allocator { }; + +// Specialization of `has_allocator` for `std::pair` +template +struct has_allocator, A> + : std::integral_constant::value || + has_allocator::value> +{ +}; + +template using boolean_constant = std::integral_constant; + +template struct is_pair : std::false_type { }; + +template +struct is_pair> : std::true_type { }; + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload is handles types for which `has_allocator` is false. +template +auto uses_allocator_args_imp(Unused1 /* is_pair */, + std::false_type /* has_allocator */, + Unused2 /* uses prefix allocator arg */, + const Alloc& /* ignored */, + Args&&... args) +{ + // Allocator is ignored + return std::forward_as_tuple(std::forward(args)...); +} + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload handles non-pair `T` for which `has_allocator` is +// true and constructor `T(allocator_arg_t, a, args...)` is valid. +template +auto uses_allocator_args_imp(std::false_type /* is_pair */, + std::true_type /* has_allocator */, + std::true_type /* uses prefix allocator arg */, + const Alloc& a, + Args&&... args) +{ + // Allocator added to front of argument list, after `allocator_arg`. + return std::tuple(std::allocator_arg, a, std::forward(args)...); +} + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload handles non-pair `T` for which `has_allocator` is +// true and constructor `T(allocator_arg_t, a, args...)` NOT valid. +// This function will produce invalid results unless `T(args..., a)` is valid. +template +auto uses_allocator_args_imp(std::false_type /* is_pair */, + std::true_type /* has_allocator */, + std::false_type /* prefix allocator arg */, + const Alloc& a, + Args&&... args) +{ + // Allocator added to end of argument list + return std::forward_as_tuple(std::forward(args)..., a); +} + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload handles specializations of `T` = `std::pair` for which +// `has_allocator` is true for either or both of the elements and +// piecewise_construct arguments are passed in. +template +auto uses_allocator_args_imp(std::true_type /* is_pair */, + std::true_type /* has_allocator */, + std::false_type /* prefix allocator arg */, + const Alloc& a, + std::piecewise_construct_t, + Tuple1&& x, Tuple2&& y) +{ + using T1 = typename T::first_type; + using T2 = typename T::second_type; + + return std::make_tuple( + std::piecewise_construct, + std::apply([&a](auto&&... args1) -> auto { + return uses_allocator_construction_args( + a, std::forward(args1)...); + }, std::forward(x)), + std::apply([&a](auto&&... args2) -> auto { + return uses_allocator_construction_args( + a, std::forward(args2)...); + }, std::forward(y)) + ); +} + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload handles specializations of `T` = `std::pair` for which +// `has_allocator` is true for either or both of the elements and +// no other constructor arguments are passed in. +template +auto uses_allocator_args_imp(std::true_type /* is_pair */, + std::true_type /* has_allocator */, + std::false_type /* prefix allocator arg */, + const Alloc& a) +{ + // using T1 = typename T::first_type; + // using T2 = typename T::second_type; + + // return std::make_tuple( + // piecewise_construct, + // uses_allocator_construction_args(a), + // uses_allocator_construction_args(a)); + return uses_allocator_construction_args(a, std::piecewise_construct, + std::tuple<>{}, std::tuple<>{}); +} + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload handles specializations of `T` = `std::pair` for which +// `has_allocator` is true for either or both of the elements and +// a single argument of type const-lvalue-of-pair is passed in. +template +auto uses_allocator_args_imp(std::true_type /* is_pair */, + std::true_type /* has_allocator */, + std::false_type /* prefix allocator arg */, + const Alloc& a, + const std::pair& arg) +{ + // using T1 = typename T::first_type; + // using T2 = typename T::second_type; + + // return std::make_tuple( + // piecewise_construct, + // uses_allocator_construction_args(a, arg.first), + // uses_allocator_construction_args(a, arg.second)); + return uses_allocator_construction_args(a, std::piecewise_construct, + std::forward_as_tuple(arg.first), + std::forward_as_tuple(arg.second)); +} + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload handles specializations of `T` = `std::pair` for which +// `has_allocator` is true for either or both of the elements and +// a single argument of type rvalue-of-pair is passed in. +template +auto uses_allocator_args_imp(std::true_type /* is_pair */, + std::true_type /* has_allocator */, + std::false_type /* prefix allocator arg */, + const Alloc& a, + std::pair&& arg) +{ + // using T1 = typename T::first_type; + // using T2 = typename T::second_type; + + // return std::make_tuple( + // piecewise_construct, + // uses_allocator_construction_args(a, forward(arg.first)), + // uses_allocator_construction_args(a, forward(arg.second))); + return uses_allocator_construction_args(a, std::piecewise_construct, + std::forward_as_tuple(std::forward(arg.first)), + std::forward_as_tuple(std::forward(arg.second))); +} + +// Return a tuple of arguments appropriate for uses-allocator construction +// with allocator `Alloc` and ctor arguments `Args`. +// This overload handles specializations of `T` = `std::pair` for which +// `has_allocator` is true for either or both of the elements and +// two additional constructor arguments are passed in. +template +auto uses_allocator_args_imp(std::true_type /* is_pair */, + std::true_type /* has_allocator */, + std::false_type /* prefix allocator arg */, + const Alloc& a, + U1&& arg1, U2&& arg2) +{ + // using T1 = typename T::first_type; + // using T2 = typename T::second_type; + + // return std::make_tuple( + // piecewise_construct, + // uses_allocator_construction_args(a, forward(arg1)), + // uses_allocator_construction_args(a, forward(arg2))); + return uses_allocator_construction_args( + a, std::piecewise_construct, + std::forward_as_tuple(std::forward(arg1)), + std::forward_as_tuple(std::forward(arg2))); +} + +} // close namespace internal + +template +auto uses_allocator_construction_args(const Alloc& a, Args&&... args) +{ + using namespace internal; + return uses_allocator_args_imp(is_pair(), + has_allocator(), + std::is_constructible(), + a, std::forward(args)...); +} + +template +T make_obj_using_allocator(const Alloc& a, Args&&... args) +{ + return make_from_tuple( + uses_allocator_construction_args(a, std::forward(args)...)); +} + +template +T* uninitialized_construct_using_allocator(T* p, + const Alloc& a, + Args&&... args) +{ + return std::apply([p](auto&&... args2){ + return ::new(static_cast(p)) + T(std::forward(args2)...); + }, uses_allocator_construction_args( + a, std::forward(args)...)); +} + +} // namespace ceph -- cgit v1.2.3