Sync from upstream.

This commit is contained in:
Rene Rivera 2024-08-08 22:00:05 -05:00
commit a6a0cd0a13
8 changed files with 233 additions and 16 deletions

View File

@ -6,6 +6,8 @@
#ifndef BOOST_UNORDERED_DETAIL_FOA_FLAT_MAP_TYPES_HPP
#define BOOST_UNORDERED_DETAIL_FOA_FLAT_MAP_TYPES_HPP
#include <boost/unordered/detail/foa/types_constructibility.hpp>
#include <boost/core/allocator_access.hpp>
namespace boost {
@ -25,6 +27,9 @@ namespace boost {
using element_type = value_type;
using types = flat_map_types<Key, T>;
using constructibility_checker = map_types_constructibility<types>;
static value_type& value_from(element_type& x) { return x; }
template <class K, class V>
@ -48,18 +53,21 @@ namespace boost {
template <class A, class... Args>
static void construct(A& al, init_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A, class... Args>
static void construct(A& al, value_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A, class... Args>
static void construct(A& al, key_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
@ -79,8 +87,8 @@ namespace boost {
}
};
} // namespace foa
} // namespace detail
} // namespace unordered
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_FOA_FLAT_MAP_TYPES_HPP

View File

@ -5,6 +5,8 @@
#ifndef BOOST_UNORDERED_DETAIL_FOA_FLAT_SET_TYPES_HPP
#define BOOST_UNORDERED_DETAIL_FOA_FLAT_SET_TYPES_HPP
#include <boost/unordered/detail/foa/types_constructibility.hpp>
#include <boost/core/allocator_access.hpp>
namespace boost {
@ -21,6 +23,9 @@ namespace boost {
using element_type = value_type;
using types = flat_set_types<Key>;
using constructibility_checker = set_types_constructibility<types>;
static Key& value_from(element_type& x) { return x; }
static element_type&& move(element_type& x) { return std::move(x); }
@ -28,6 +33,7 @@ namespace boost {
template <class A, class... Args>
static void construct(A& al, value_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
@ -37,8 +43,8 @@ namespace boost {
}
};
} // namespace foa
} // namespace detail
} // namespace unordered
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_FOA_FLAT_SET_TYPES_HPP

View File

@ -7,6 +7,8 @@
#define BOOST_UNORDERED_DETAIL_FOA_NODE_MAP_TYPES_HPP
#include <boost/unordered/detail/foa/element_type.hpp>
#include <boost/unordered/detail/foa/types_constructibility.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/core/no_exceptions_support.hpp>
@ -29,6 +31,9 @@ namespace boost {
using element_type = foa::element_type<value_type, VoidPtr>;
using types = node_map_types<Key, T, VoidPtr>;
using constructibility_checker = map_types_constructibility<types>;
static value_type& value_from(element_type const& x)
{
return *(x.p);
@ -68,24 +73,27 @@ namespace boost {
static void construct(
A& al, element_type* p, element_type const& copy)
{
construct(al, p, *copy.p);
construct(al, p, detail::as_const(*copy.p));
}
template <class A, class... Args>
static void construct(A& al, init_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A, class... Args>
static void construct(A& al, value_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
template <class A, class... Args>
static void construct(A& al, key_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
@ -95,8 +103,11 @@ namespace boost {
p->p = boost::allocator_allocate(al, 1);
BOOST_TRY
{
auto address = boost::to_address(p->p);
constructibility_checker::check(
al, address, std::forward<Args>(args)...);
boost::allocator_construct(
al, boost::to_address(p->p), std::forward<Args>(args)...);
al, address, std::forward<Args>(args)...);
}
BOOST_CATCH(...)
{
@ -132,8 +143,8 @@ namespace boost {
};
} // namespace foa
} // namespace detail
} // namespace unordered
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_FOA_NODE_MAP_TYPES_HPP

View File

@ -6,6 +6,8 @@
#define BOOST_UNORDERED_DETAIL_FOA_NODE_SET_TYPES_HPP
#include <boost/unordered/detail/foa/element_type.hpp>
#include <boost/unordered/detail/foa/types_constructibility.hpp>
#include <boost/unordered/detail/type_traits.hpp>
#include <boost/core/allocator_access.hpp>
#include <boost/core/no_exceptions_support.hpp>
@ -26,6 +28,9 @@ namespace boost {
using element_type = foa::element_type<value_type, VoidPtr>;
using types = node_set_types<Key, VoidPtr>;
using constructibility_checker = set_types_constructibility<types>;
static value_type& value_from(element_type const& x) { return *x.p; }
static Key const& extract(element_type const& k) { return *k.p; }
static element_type&& move(element_type& x) { return std::move(x); }
@ -35,7 +40,7 @@ namespace boost {
static void construct(
A& al, element_type* p, element_type const& copy)
{
construct(al, p, *copy.p);
construct(al, p, detail::as_const(*copy.p));
}
template <typename Allocator>
@ -49,6 +54,7 @@ namespace boost {
template <class A, class... Args>
static void construct(A& al, value_type* p, Args&&... args)
{
constructibility_checker::check(al, p, std::forward<Args>(args)...);
boost::allocator_construct(al, p, std::forward<Args>(args)...);
}
@ -58,8 +64,11 @@ namespace boost {
p->p = boost::allocator_allocate(al, 1);
BOOST_TRY
{
auto address = boost::to_address(p->p);
constructibility_checker::check(
al, address, std::forward<Args>(args)...);
boost::allocator_construct(
al, boost::to_address(p->p), std::forward<Args>(args)...);
al, address, std::forward<Args>(args)...);
}
BOOST_CATCH(...)
{
@ -85,8 +94,8 @@ namespace boost {
};
} // namespace foa
} // namespace detail
} // namespace unordered
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_FOA_NODE_SET_TYPES_HPP

View File

@ -0,0 +1,172 @@
// Copyright (C) 2024 Braden Ganetsky
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_UNORDERED_DETAIL_FOA_TYPES_CONSTRUCTIBILITY_HPP
#define BOOST_UNORDERED_DETAIL_FOA_TYPES_CONSTRUCTIBILITY_HPP
#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>
namespace boost {
namespace unordered {
namespace detail {
namespace foa {
template <class Key, class... Args> struct check_key_type_t
{
static_assert(std::is_constructible<Key, Args...>::value,
"key_type must be constructible from Args");
};
template <class Key> struct check_key_type_t<Key>
{
static_assert(std::is_constructible<Key>::value,
"key_type must be default constructible");
};
template <class Key> struct check_key_type_t<Key, const Key&>
{
static_assert(std::is_constructible<Key, const Key&>::value,
"key_type must be copy constructible");
};
template <class Key> struct check_key_type_t<Key, Key&&>
{
static_assert(std::is_constructible<Key, Key&&>::value,
"key_type must be move constructible");
};
template <class Mapped, class... Args> struct check_mapped_type_t
{
static_assert(std::is_constructible<Mapped, Args...>::value,
"mapped_type must be constructible from Args");
};
template <class Mapped> struct check_mapped_type_t<Mapped>
{
static_assert(std::is_constructible<Mapped>::value,
"mapped_type must be default constructible");
};
template <class Mapped>
struct check_mapped_type_t<Mapped, const Mapped&>
{
static_assert(std::is_constructible<Mapped, const Mapped&>::value,
"mapped_type must be copy constructible");
};
template <class Mapped> struct check_mapped_type_t<Mapped, Mapped&&>
{
static_assert(std::is_constructible<Mapped, Mapped&&>::value,
"mapped_type must be move constructible");
};
template <class TypePolicy> struct map_types_constructibility
{
using key_type = typename TypePolicy::key_type;
using mapped_type = typename TypePolicy::mapped_type;
using init_type = typename TypePolicy::init_type;
using value_type = typename TypePolicy::value_type;
template <class A, class X, class... Args>
static void check(A&, X*, Args&&...)
{
// Pass through, as we cannot say anything about a general allocator
}
template <class... Args> static void check_key_type()
{
(void)check_key_type_t<key_type, Args...>{};
}
template <class... Args> static void check_mapped_type()
{
(void)check_mapped_type_t<mapped_type, Args...>{};
}
template <class Arg>
static void check(std::allocator<value_type>&, key_type*, Arg&&)
{
check_key_type<Arg&&>();
}
template <class Arg1, class Arg2>
static void check(
std::allocator<value_type>&, value_type*, Arg1&&, Arg2&&)
{
check_key_type<Arg1&&>();
check_mapped_type<Arg2&&>();
}
template <class Arg1, class Arg2>
static void check(std::allocator<value_type>&, value_type*,
const std::pair<Arg1, Arg2>&)
{
check_key_type<const Arg1&>();
check_mapped_type<const Arg2&>();
}
template <class Arg1, class Arg2>
static void check(
std::allocator<value_type>&, value_type*, std::pair<Arg1, Arg2>&&)
{
check_key_type<Arg1&&>();
check_mapped_type<Arg2&&>();
}
template <class... Args1, class... Args2>
static void check(std::allocator<value_type>&, value_type*,
std::piecewise_construct_t, std::tuple<Args1...>&&,
std::tuple<Args2...>&&)
{
check_key_type<Args1&&...>();
check_mapped_type<Args2&&...>();
}
template <class Arg1, class Arg2>
static void check(
std::allocator<value_type>&, init_type*, Arg1&&, Arg2&&)
{
check_key_type<Arg1&&>();
check_mapped_type<Arg2&&>();
}
template <class Arg1, class Arg2>
static void check(std::allocator<value_type>&, init_type*,
const std::pair<Arg1, Arg2>&)
{
check_key_type<const Arg1&>();
check_mapped_type<const Arg2&>();
}
template <class Arg1, class Arg2>
static void check(
std::allocator<value_type>&, init_type*, std::pair<Arg1, Arg2>&&)
{
check_key_type<Arg1&&>();
check_mapped_type<Arg2&&>();
}
template <class... Args1, class... Args2>
static void check(std::allocator<value_type>&, init_type*,
std::piecewise_construct_t, std::tuple<Args1...>&&,
std::tuple<Args2...>&&)
{
check_key_type<Args1&&...>();
check_mapped_type<Args2&&...>();
}
};
template <class TypePolicy> struct set_types_constructibility
{
using key_type = typename TypePolicy::key_type;
using value_type = typename TypePolicy::value_type;
static_assert(std::is_same<key_type, value_type>::value, "");
template <class A, class X, class... Args>
static void check(A&, X*, Args&&...)
{
// Pass through, as we cannot say anything about a general allocator
}
template <class... Args>
static void check(std::allocator<value_type>&, key_type*, Args&&...)
{
(void)check_key_type_t<key_type, Args&&...>{};
}
};
} // namespace foa
} // namespace detail
} // namespace unordered
} // namespace boost
#endif // BOOST_UNORDERED_DETAIL_FOA_TYPES_CONSTRUCTIBILITY_HPP

View File

@ -219,6 +219,17 @@ namespace boost {
using iter_to_alloc_t =
typename std::pair<iter_key_t<T> const, iter_val_t<T> >;
#endif
#if BOOST_CXX_VERSION < 201703L
template <class T>
constexpr typename std::add_const<T>::type& as_const(T& t) noexcept
{
return t;
}
template <class T> void as_const(const T&&) = delete;
#else
using std::as_const;
#endif
} // namespace detail
} // namespace unordered
} // namespace boost

View File

@ -198,7 +198,7 @@ namespace boost {
template <class... Args> std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace_unique(
table::extractor::extract(std::forward<Args>(args)...),
table::extractor::extract(detail::as_const(args)...),
std::forward<Args>(args)...);
}
@ -206,7 +206,7 @@ namespace boost {
iterator emplace_hint(const_iterator hint, Args&&... args)
{
return table_.emplace_hint_unique(hint,
table::extractor::extract(std::forward<Args>(args)...),
table::extractor::extract(detail::as_const(args)...),
std::forward<Args>(args)...);
}

View File

@ -194,7 +194,7 @@ namespace boost {
template <class... Args> std::pair<iterator, bool> emplace(Args&&... args)
{
return table_.emplace_unique(
table::extractor::extract(std::forward<Args>(args)...),
table::extractor::extract(detail::as_const(args)...),
std::forward<Args>(args)...);
}
@ -202,7 +202,7 @@ namespace boost {
iterator emplace_hint(const_iterator hint, Args&&... args)
{
return table_.emplace_hint_unique(hint,
table::extractor::extract(std::forward<Args>(args)...),
table::extractor::extract(detail::as_const(args)...),
std::forward<Args>(args)...);
}