1*7c82a1ecSDimitry Andric// -*- C++ -*-
2*7c82a1ecSDimitry Andric//===----------------------------------------------------------------------===//
3*7c82a1ecSDimitry Andric//
4*7c82a1ecSDimitry Andric//                     The LLVM Compiler Infrastructure
5*7c82a1ecSDimitry Andric//
6*7c82a1ecSDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open
7*7c82a1ecSDimitry Andric// Source Licenses. See LICENSE.TXT for details.
8*7c82a1ecSDimitry Andric//
9*7c82a1ecSDimitry Andric//===----------------------------------------------------------------------===//
10*7c82a1ecSDimitry Andric
11*7c82a1ecSDimitry Andric#ifndef _LIBCPP_EXPERIMENTAL___MEMORY
12*7c82a1ecSDimitry Andric#define _LIBCPP_EXPERIMENTAL___MEMORY
13*7c82a1ecSDimitry Andric
14*7c82a1ecSDimitry Andric#include <experimental/__config>
15*7c82a1ecSDimitry Andric#include <experimental/utility> // for erased_type
16*7c82a1ecSDimitry Andric#include <__functional_base>
17*7c82a1ecSDimitry Andric#include <type_traits>
18*7c82a1ecSDimitry Andric
19*7c82a1ecSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_LFTS
20*7c82a1ecSDimitry Andric
21*7c82a1ecSDimitry Andrictemplate <
22*7c82a1ecSDimitry Andric    class _Tp, class _Alloc
23*7c82a1ecSDimitry Andric  , bool = uses_allocator<_Tp, _Alloc>::value
24*7c82a1ecSDimitry Andric  , bool = __has_allocator_type<_Tp>::value
25*7c82a1ecSDimitry Andric  >
26*7c82a1ecSDimitry Andricstruct __lfts_uses_allocator : public false_type {};
27*7c82a1ecSDimitry Andric
28*7c82a1ecSDimitry Andrictemplate <class _Tp, class _Alloc>
29*7c82a1ecSDimitry Andricstruct __lfts_uses_allocator<_Tp, _Alloc, false, false> : public false_type {};
30*7c82a1ecSDimitry Andric
31*7c82a1ecSDimitry Andrictemplate <class _Tp, class _Alloc, bool HasAlloc>
32*7c82a1ecSDimitry Andricstruct __lfts_uses_allocator<_Tp, _Alloc, true, HasAlloc> : public true_type {};
33*7c82a1ecSDimitry Andric
34*7c82a1ecSDimitry Andrictemplate <class _Tp, class _Alloc>
35*7c82a1ecSDimitry Andricstruct __lfts_uses_allocator<_Tp, _Alloc, false, true>
36*7c82a1ecSDimitry Andric  : public integral_constant<bool
37*7c82a1ecSDimitry Andric    , is_convertible<_Alloc, typename _Tp::allocator_type>::value
38*7c82a1ecSDimitry Andric      || is_same<erased_type, typename _Tp::allocator_type>::value
39*7c82a1ecSDimitry Andric    >
40*7c82a1ecSDimitry Andric{};
41*7c82a1ecSDimitry Andric
42*7c82a1ecSDimitry Andrictemplate <bool _UsesAlloc, class _Tp, class _Alloc, class ..._Args>
43*7c82a1ecSDimitry Andricstruct __lfts_uses_alloc_ctor_imp
44*7c82a1ecSDimitry Andric{
45*7c82a1ecSDimitry Andric    static const int value = 0;
46*7c82a1ecSDimitry Andric};
47*7c82a1ecSDimitry Andric
48*7c82a1ecSDimitry Andrictemplate <class _Tp, class _Alloc, class ..._Args>
49*7c82a1ecSDimitry Andricstruct __lfts_uses_alloc_ctor_imp<true, _Tp, _Alloc, _Args...>
50*7c82a1ecSDimitry Andric{
51*7c82a1ecSDimitry Andric    static const bool __ic_first
52*7c82a1ecSDimitry Andric        = is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value;
53*7c82a1ecSDimitry Andric
54*7c82a1ecSDimitry Andric    static const bool __ic_second =
55*7c82a1ecSDimitry Andric        conditional<
56*7c82a1ecSDimitry Andric            __ic_first,
57*7c82a1ecSDimitry Andric            false_type,
58*7c82a1ecSDimitry Andric            is_constructible<_Tp, _Args..., _Alloc>
59*7c82a1ecSDimitry Andric        >::type::value;
60*7c82a1ecSDimitry Andric
61*7c82a1ecSDimitry Andric    static_assert(__ic_first || __ic_second,
62*7c82a1ecSDimitry Andric                  "Request for uses allocator construction is ill-formed");
63*7c82a1ecSDimitry Andric
64*7c82a1ecSDimitry Andric    static const int value = __ic_first ? 1 : 2;
65*7c82a1ecSDimitry Andric};
66*7c82a1ecSDimitry Andric
67*7c82a1ecSDimitry Andrictemplate <class _Tp, class _Alloc, class ..._Args>
68*7c82a1ecSDimitry Andricstruct __lfts_uses_alloc_ctor
69*7c82a1ecSDimitry Andric  : integral_constant<int,
70*7c82a1ecSDimitry Andric        __lfts_uses_alloc_ctor_imp<
71*7c82a1ecSDimitry Andric            __lfts_uses_allocator<_Tp, _Alloc>::value
72*7c82a1ecSDimitry Andric          , _Tp, _Alloc, _Args...
73*7c82a1ecSDimitry Andric        >::value
74*7c82a1ecSDimitry Andric    >
75*7c82a1ecSDimitry Andric{};
76*7c82a1ecSDimitry Andric
77*7c82a1ecSDimitry Andrictemplate <class _Tp, class _Alloc, class ..._Args>
78*7c82a1ecSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
79*7c82a1ecSDimitry Andricvoid __lfts_user_alloc_construct(
80*7c82a1ecSDimitry Andric    _Tp * __store, const _Alloc & __a, _Args &&... __args)
81*7c82a1ecSDimitry Andric{
82*7c82a1ecSDimitry Andric    _VSTD::__user_alloc_construct_impl(
83*7c82a1ecSDimitry Andric        typename __lfts_uses_alloc_ctor<_Tp, _Alloc, _Args...>::type()
84*7c82a1ecSDimitry Andric       , __store, __a, _VSTD::forward<_Args>(__args)...
85*7c82a1ecSDimitry Andric       );
86*7c82a1ecSDimitry Andric}
87*7c82a1ecSDimitry Andric
88*7c82a1ecSDimitry Andric_LIBCPP_END_NAMESPACE_LFTS
89*7c82a1ecSDimitry Andric
90*7c82a1ecSDimitry Andric#endif /* _LIBCPP_EXPERIMENTAL___MEMORY */
91