unordered_map.h (unordered_map, [...]): Add missing constructors.
[gcc.git] / libstdc++-v3 / include / bits / alloc_traits.h
index 80cc956a6fbf52702bea1538729c66aac6004d9e..e434261802fcf1b5f5e95616650da1b7a155f69d 100644 (file)
@@ -1,6 +1,6 @@
 // Allocator traits -*- C++ -*-
 
-// Copyright (C) 2011-2012 Free Software Foundation, Inc.
+// Copyright (C) 2011-2015 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
@@ -30,8 +30,9 @@
 #ifndef _ALLOC_TRAITS_H
 #define _ALLOC_TRAITS_H 1
 
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#if __cplusplus >= 201103L
 
+#include <bits/memoryfwd.h>
 #include <bits/ptr_traits.h>
 #include <ext/numeric_traits.h>
 
@@ -43,24 +44,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     class __alloctr_rebind_helper
     {
       template<typename _Alloc2, typename _Tp2>
-       static constexpr bool
-               _S_chk(typename _Alloc2::template rebind<_Tp2>::other*)
-       { return true; }
+       static constexpr true_type
+       _S_chk(typename _Alloc2::template rebind<_Tp2>::other*);
 
       template<typename, typename>
-        static constexpr bool
-               _S_chk(...)
-               { return false; }
+       static constexpr false_type
+       _S_chk(...);
 
     public:
-      static const bool __value = _S_chk<_Alloc, _Tp>(nullptr);
+      using __type = decltype(_S_chk<_Alloc, _Tp>(nullptr));
     };
 
-  template<typename _Alloc, typename _Tp>
-    const bool __alloctr_rebind_helper<_Alloc, _Tp>::__value;
-
   template<typename _Alloc, typename _Tp,
-           bool = __alloctr_rebind_helper<_Alloc, _Tp>::__value>
+          bool = __alloctr_rebind_helper<_Alloc, _Tp>::__type::value>
     struct __alloctr_rebind;
 
   template<typename _Alloc, typename _Tp>
@@ -70,12 +66,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
   template<template<typename, typename...> class _Alloc, typename _Tp,
-            typename _Up, typename... _Args>
+          typename _Up, typename... _Args>
     struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false>
     {
       typedef _Alloc<_Tp, _Args...> __type;
     };
 
+  template<typename _Alloc, typename _Tp>
+    using __alloc_rebind = typename __alloctr_rebind<_Alloc, _Tp>::__type;
+
   /**
    * @brief  Uniform interface to all allocator types.
    * @ingroup allocators
@@ -139,7 +138,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer,
       typedef __const_void_pointer const_void_pointer;
 
 _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type,
-                              typename pointer_traits<pointer>::difference_type)
+                             typename pointer_traits<pointer>::difference_type)
 
       /**
        * @brief   The allocator's difference type
@@ -150,7 +149,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type,
       typedef __difference_type difference_type;
 
 _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type,
-                              typename make_unsigned<difference_type>::type)
+                             typename make_unsigned<difference_type>::type)
 
       /**
        * @brief   The allocator's size type
@@ -161,7 +160,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type,
       typedef __size_type size_type;
 
 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment,
-                              false_type)
+                             false_type)
 
       /**
        * @brief   How the allocator is propagated on copy assignment
@@ -170,10 +169,10 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment,
        * otherwise @c false_type
       */
       typedef __propagate_on_container_copy_assignment
-               propagate_on_container_copy_assignment;
+       propagate_on_container_copy_assignment;
 
 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment,
-                              false_type)
+                             false_type)
 
       /**
        * @brief   How the allocator is propagated on move assignment
@@ -182,10 +181,10 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment,
        * otherwise @c false_type
       */
       typedef __propagate_on_container_move_assignment
-               propagate_on_container_move_assignment;
+       propagate_on_container_move_assignment;
 
 _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
-                              false_type)
+                             false_type)
 
       /**
        * @brief   How the allocator is propagated on swap
@@ -198,9 +197,9 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
 #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE
 
       template<typename _Tp>
-        using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
+       using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;
       template<typename _Tp>
-        using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
+       using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
 
     private:
       template<typename _Alloc2>
@@ -215,20 +214,22 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
          template<typename>
            static false_type __test(...);
 
-         typedef decltype(__test<_Alloc>(0)) type;
-         static const bool value = type::value;
+         using type = decltype(__test<_Alloc>(0));
        };
 
       template<typename _Alloc2>
-       static typename
-               enable_if<__allocate_helper<_Alloc2>::value, pointer>::type
-               _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint)
+       using __has_allocate = typename __allocate_helper<_Alloc2>::type;
+
+      template<typename _Alloc2,
+              typename = _Require<__has_allocate<_Alloc2>>>
+       static pointer
+       _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint)
        { return __a.allocate(__n, __hint); }
 
-      template<typename _Alloc2>
-       static typename
-               enable_if<!__allocate_helper<_Alloc2>::value, pointer>::type
-               _S_allocate(_Alloc2& __a, size_type __n, ...)
+      template<typename _Alloc2, typename _UnusedHint,
+              typename = _Require<__not_<__has_allocate<_Alloc2>>>>
+       static pointer
+       _S_allocate(_Alloc2& __a, size_type __n, _UnusedHint)
        { return __a.allocate(__n); }
 
       template<typename _Tp, typename... _Args>
@@ -242,20 +243,23 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
          template<typename>
            static false_type __test(...);
 
-         typedef decltype(__test<_Alloc>(0)) type;
-         static const bool value = type::value;
+         using type = decltype(__test<_Alloc>(0));
        };
 
       template<typename _Tp, typename... _Args>
-       static typename
-               enable_if<__construct_helper<_Tp, _Args...>::value, void>::type
-               _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+       using __has_construct
+         = typename __construct_helper<_Tp, _Args...>::type;
+
+      template<typename _Tp, typename... _Args>
+       static _Require<__has_construct<_Tp, _Args...>>
+       _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
        { __a.construct(__p, std::forward<_Args>(__args)...); }
 
       template<typename _Tp, typename... _Args>
-       static typename
-               enable_if<!__construct_helper<_Tp, _Args...>::value, void>::type
-               _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
+       static
+       _Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
+                              is_constructible<_Tp, _Args...>>>
+       _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
        { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }
 
       template<typename _Tp>
@@ -269,18 +273,20 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
          template<typename>
            static false_type __test(...);
 
-         typedef decltype(__test<_Alloc>(0)) type;
-         static const bool value = type::value;
+         using type = decltype(__test<_Alloc>(0));
        };
 
       template<typename _Tp>
-       static typename enable_if<__destroy_helper<_Tp>::value, void>::type
-               _S_destroy(_Alloc& __a, _Tp* __p)
+       using __has_destroy = typename __destroy_helper<_Tp>::type;
+
+      template<typename _Tp>
+       static _Require<__has_destroy<_Tp>>
+       _S_destroy(_Alloc& __a, _Tp* __p)
        { __a.destroy(__p); }
 
       template<typename _Tp>
-       static typename enable_if<!__destroy_helper<_Tp>::value, void>::type
-               _S_destroy(_Alloc&, _Tp* __p)
+       static _Require<__not_<__has_destroy<_Tp>>>
+       _S_destroy(_Alloc&, _Tp* __p)
        { __p->~_Tp(); }
 
       template<typename _Alloc2>
@@ -293,21 +299,28 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
          template<typename>
            static false_type __test(...);
 
-         typedef decltype(__test<_Alloc2>(0)) type;
-         static const bool value = type::value;
+         using type = decltype(__test<_Alloc2>(0));
        };
 
       template<typename _Alloc2>
-       static typename
-               enable_if<__maxsize_helper<_Alloc2>::value, size_type>::type
-               _S_max_size(_Alloc2& __a)
+       using __has_max_size = typename __maxsize_helper<_Alloc2>::type;
+
+      template<typename _Alloc2,
+              typename = _Require<__has_max_size<_Alloc2>>>
+       static size_type
+       _S_max_size(_Alloc2& __a, int)
        { return __a.max_size(); }
 
-      template<typename _Alloc2>
-       static typename
-               enable_if<!__maxsize_helper<_Alloc2>::value, size_type>::type
-       _S_max_size(_Alloc2&)
-       { return __gnu_cxx::__numeric_traits<size_type>::__max; }
+      template<typename _Alloc2,
+              typename = _Require<__not_<__has_max_size<_Alloc2>>>>
+       static size_type
+       _S_max_size(_Alloc2&, ...)
+       {
+         // _GLIBCXX_RESOLVE_LIB_DEFECTS
+         // 2466. allocator_traits::max_size() default behavior is incorrect
+         return __gnu_cxx::__numeric_traits<size_type>::__max
+           / sizeof(value_type);
+       }
 
       template<typename _Alloc2>
        struct __select_helper
@@ -320,19 +333,22 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
          template<typename>
            static false_type __test(...);
 
-         typedef decltype(__test<_Alloc2>(0)) type;
-         static const bool value = type::value;
+         using type = decltype(__test<_Alloc2>(0));
        };
+
       template<typename _Alloc2>
-       static typename
-               enable_if<__select_helper<_Alloc2>::value, _Alloc2>::type
-               _S_select(_Alloc2& __a)
+       using __has_soccc = typename __select_helper<_Alloc2>::type;
+
+      template<typename _Alloc2,
+              typename = _Require<__has_soccc<_Alloc2>>>
+       static _Alloc2
+       _S_select(_Alloc2& __a, int)
        { return __a.select_on_container_copy_construction(); }
 
-      template<typename _Alloc2>
-       static typename
-               enable_if<!__select_helper<_Alloc2>::value, _Alloc2>::type
-               _S_select(_Alloc2& __a)
+      template<typename _Alloc2,
+              typename = _Require<__not_<__has_soccc<_Alloc2>>>>
+       static _Alloc2
+       _S_select(_Alloc2& __a, ...)
        { return __a; }
 
     public:
@@ -386,7 +402,8 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
        *  arguments @a __args...
       */
       template<typename _Tp, typename... _Args>
-       static void construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+       static auto construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
+       -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
        { _S_construct(__a, __p, std::forward<_Args>(__args)...); }
 
       /**
@@ -409,8 +426,8 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
        *  Returns @c __a.max_size() if that expression is well-formed,
        *  otherwise returns @c numeric_limits<size_type>::max()
       */
-      static size_type max_size(const _Alloc& __a)
-      { return _S_max_size(__a); }
+      static size_type max_size(const _Alloc& __a) noexcept
+      { return _S_max_size(__a, 0); }
 
       /**
        *  @brief  Obtain an allocator to use when copying a container.
@@ -422,30 +439,9 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
       */
       static _Alloc
       select_on_container_copy_construction(const _Alloc& __rhs)
-      { return _S_select(__rhs); }
+      { return _S_select(__rhs, 0); }
     };
 
-  template<typename _Alloc>
-  template<typename _Alloc2>
-    const bool allocator_traits<_Alloc>::__allocate_helper<_Alloc2>::value;
-
-  template<typename _Alloc>
-  template<typename _Tp, typename... _Args>
-    const bool
-    allocator_traits<_Alloc>::__construct_helper<_Tp, _Args...>::value;
-
-  template<typename _Alloc>
-  template<typename _Tp>
-    const bool allocator_traits<_Alloc>::__destroy_helper<_Tp>::value;
-
-  template<typename _Alloc>
-  template<typename _Alloc2>
-    const bool allocator_traits<_Alloc>::__maxsize_helper<_Alloc2>::value;
-
-  template<typename _Alloc>
-  template<typename _Alloc2>
-    const bool allocator_traits<_Alloc>::__select_helper<_Alloc2>::value;
-
   template<typename _Alloc>
     inline void
     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
@@ -506,6 +502,38 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
       __do_alloc_on_swap(__one, __two, __pocs());
     }
 
+  template<typename _Alloc>
+    class __is_copy_insertable_impl
+    {
+      typedef allocator_traits<_Alloc> _Traits;
+
+      template<typename _Up, typename
+              = decltype(_Traits::construct(std::declval<_Alloc&>(),
+                                            std::declval<_Up*>(),
+                                            std::declval<const _Up&>()))>
+       static true_type
+       _M_select(int);
+
+      template<typename _Up>
+       static false_type
+       _M_select(...);
+
+    public:
+      typedef decltype(_M_select<typename _Alloc::value_type>(0)) type;
+    };
+
+  // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
+  template<typename _Alloc>
+    struct __is_copy_insertable
+    : __is_copy_insertable_impl<_Alloc>::type
+    { };
+
+  // std::allocator<_Tp> just requires CopyConstructible
+  template<typename _Tp>
+    struct __is_copy_insertable<allocator<_Tp>>
+    : is_copy_constructible<_Tp>
+    { };
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std