123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- // Uses-allocator Construction -*- C++ -*-
- // Copyright (C) 2010-2022 Free Software Foundation, Inc.
- //
- // This file is part of the GNU ISO C++ Library. This library is free
- // software; you can redistribute it and/or modify it under the
- // terms of the GNU General Public License as published by the
- // Free Software Foundation; either version 3, or (at your option)
- // any later version.
- // This library 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.
- // Under Section 7 of GPL version 3, you are granted additional
- // permissions described in the GCC Runtime Library Exception, version
- // 3.1, as published by the Free Software Foundation.
- // You should have received a copy of the GNU General Public License and
- // a copy of the GCC Runtime Library Exception along with this program;
- // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- // <http://www.gnu.org/licenses/>.
- #ifndef _USES_ALLOCATOR_H
- #define _USES_ALLOCATOR_H 1
- #if __cplusplus < 201103L
- # include <bits/c++0x_warning.h>
- #else
- #include <type_traits>
- #include <bits/move.h>
- namespace std _GLIBCXX_VISIBILITY(default)
- {
- _GLIBCXX_BEGIN_NAMESPACE_VERSION
- /// @cond undocumented
- // This is used for std::experimental::erased_type from Library Fundamentals.
- struct __erased_type { };
- // This also supports the "type-erased allocator" protocol from the
- // Library Fundamentals TS, where allocator_type is erased_type.
- // The second condition will always be false for types not using the TS.
- template<typename _Alloc, typename _Tp>
- using __is_erased_or_convertible
- = __or_<is_convertible<_Alloc, _Tp>, is_same<_Tp, __erased_type>>;
- /// [allocator.tag]
- struct allocator_arg_t { explicit allocator_arg_t() = default; };
- _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg =
- allocator_arg_t();
- template<typename _Tp, typename _Alloc, typename = __void_t<>>
- struct __uses_allocator_helper
- : false_type { };
- template<typename _Tp, typename _Alloc>
- struct __uses_allocator_helper<_Tp, _Alloc,
- __void_t<typename _Tp::allocator_type>>
- : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type
- { };
- /// [allocator.uses.trait]
- template<typename _Tp, typename _Alloc>
- struct uses_allocator
- : __uses_allocator_helper<_Tp, _Alloc>::type
- { };
- struct __uses_alloc_base { };
- struct __uses_alloc0 : __uses_alloc_base
- {
- struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a;
- };
- template<typename _Alloc>
- struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
- template<typename _Alloc>
- struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
- template<bool, typename _Tp, typename _Alloc, typename... _Args>
- struct __uses_alloc;
- template<typename _Tp, typename _Alloc, typename... _Args>
- struct __uses_alloc<true, _Tp, _Alloc, _Args...>
- : __conditional_t<
- is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value,
- __uses_alloc1<_Alloc>,
- __uses_alloc2<_Alloc>>
- {
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 2586. Wrong value category used in scoped_allocator_adaptor::construct
- static_assert(__or_<
- is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>,
- is_constructible<_Tp, _Args..., const _Alloc&>>::value,
- "construction with an allocator must be possible"
- " if uses_allocator is true");
- };
- template<typename _Tp, typename _Alloc, typename... _Args>
- struct __uses_alloc<false, _Tp, _Alloc, _Args...>
- : __uses_alloc0 { };
- template<typename _Tp, typename _Alloc, typename... _Args>
- using __uses_alloc_t =
- __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
- template<typename _Tp, typename _Alloc, typename... _Args>
- _GLIBCXX20_CONSTEXPR
- inline __uses_alloc_t<_Tp, _Alloc, _Args...>
- __use_alloc(const _Alloc& __a)
- {
- __uses_alloc_t<_Tp, _Alloc, _Args...> __ret;
- __ret._M_a = std::__addressof(__a);
- return __ret;
- }
- template<typename _Tp, typename _Alloc, typename... _Args>
- void
- __use_alloc(const _Alloc&&) = delete;
- #if __cplusplus > 201402L
- template <typename _Tp, typename _Alloc>
- inline constexpr bool uses_allocator_v =
- uses_allocator<_Tp, _Alloc>::value;
- #endif // C++17
- template<template<typename...> class _Predicate,
- typename _Tp, typename _Alloc, typename... _Args>
- struct __is_uses_allocator_predicate
- : __conditional_t<uses_allocator<_Tp, _Alloc>::value,
- __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>,
- _Predicate<_Tp, _Args..., _Alloc>>,
- _Predicate<_Tp, _Args...>> { };
- template<typename _Tp, typename _Alloc, typename... _Args>
- struct __is_uses_allocator_constructible
- : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...>
- { };
- #if __cplusplus >= 201402L
- template<typename _Tp, typename _Alloc, typename... _Args>
- _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v =
- __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
- #endif // C++14
- template<typename _Tp, typename _Alloc, typename... _Args>
- struct __is_nothrow_uses_allocator_constructible
- : __is_uses_allocator_predicate<is_nothrow_constructible,
- _Tp, _Alloc, _Args...>
- { };
- #if __cplusplus >= 201402L
- template<typename _Tp, typename _Alloc, typename... _Args>
- _GLIBCXX17_INLINE constexpr bool
- __is_nothrow_uses_allocator_constructible_v =
- __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
- #endif // C++14
- template<typename _Tp, typename... _Args>
- void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr,
- _Args&&... __args)
- { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); }
- template<typename _Tp, typename _Alloc, typename... _Args>
- void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr,
- _Args&&... __args)
- {
- ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a,
- std::forward<_Args>(__args)...);
- }
- template<typename _Tp, typename _Alloc, typename... _Args>
- void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr,
- _Args&&... __args)
- { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); }
- template<typename _Tp, typename _Alloc, typename... _Args>
- void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
- _Args&&... __args)
- {
- std::__uses_allocator_construct_impl(
- std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr,
- std::forward<_Args>(__args)...);
- }
- /// @endcond
- _GLIBCXX_END_NAMESPACE_VERSION
- } // namespace std
- #endif
- #endif
|