[cfe-commits] [libcxx] r111672 - in /libcxx/trunk: include/ test/utilities/function.objects/func.wrap/func.wrap.func/ test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/ test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/

Howard Hinnant hhinnant at apple.com
Fri Aug 20 12:36:46 PDT 2010


Author: hhinnant
Date: Fri Aug 20 14:36:46 2010
New Revision: 111672

URL: http://llvm.org/viewvc/llvm-project?rev=111672&view=rev
Log:
Installed allocator into std::function

Added:
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h
Modified:
    libcxx/trunk/include/__functional_03
    libcxx/trunk/include/functional
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp
    libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp

Modified: libcxx/trunk/include/__functional_03
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__functional_03?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/include/__functional_03 (original)
+++ libcxx/trunk/include/__functional_03 Fri Aug 20 14:36:46 2010
@@ -367,7 +367,7 @@
 _R
 __func<_F, _Alloc, _R()>::operator()()
 {
-    return __invoke<_R>(__f_.first());
+    return __invoke(__f_.first());
 }
 
 #ifndef _LIBCPP_NO_RTTI
@@ -660,16 +660,15 @@
       function(_F,
                typename enable_if<!is_integral<_F>::value>::type* = 0);
 
-//     template<class _Alloc>
-//       function(allocator_arg_t, const _Alloc&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, nullptr_t);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, const function&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, function&&);
-//     template<class F, Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, F);
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, const function&);
+    template<class _F, class _Alloc>
+      function(allocator_arg_t, const _Alloc& __a, _F __f,
+               typename enable_if<!is_integral<_F>::value>::type* = 0);
 
     function& operator=(const function&);
     function& operator=(nullptr_t);
@@ -685,8 +684,9 @@
 
     // 20.7.16.2.2, function modifiers:
     void swap(function&);
-//     template<class _F, class _Alloc>
-//       void assign(_F, const _Alloc&);
+    template<class _F, class _Alloc>
+      void assign(_F __f, const _Alloc& __a)
+        {function(allocator_arg, __a, __f).swap(*this);}
 
     // 20.7.16.2.3, function capacity:
     operator bool() const {return __f_;}
@@ -724,6 +724,21 @@
 }
 
 template<class _R>
+template<class _Alloc>
+function<_R()>::function(allocator_arg_t, const _Alloc&, const function& __f)
+{
+    if (__f.__f_ == 0)
+        __f_ = 0;
+    else if (__f.__f_ == (const __base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__clone(__f_);
+    }
+    else
+        __f_ = __f.__f_->__clone();
+}
+
+template<class _R>
 template <class _F>
 function<_R()>::function(_F __f,
                                      typename enable_if<!is_integral<_F>::value>::type*)
@@ -750,6 +765,39 @@
 }
 
 template<class _R>
+template <class _F, class _Alloc>
+function<_R()>::function(allocator_arg_t, const _Alloc& __a0, _F __f,
+                                     typename enable_if<!is_integral<_F>::value>::type*)
+    : __f_(0)
+{
+    typedef allocator_traits<_Alloc> __alloc_traits;
+    if (__not_null(__f))
+    {
+        typedef __function::__func<_F, _Alloc, _R()> _FF;
+        if (sizeof(_FF) <= sizeof(__buf_))
+        {
+            __f_ = (__base*)&__buf_;
+            ::new (__f_) _FF(__f);
+        }
+        else
+        {
+            typedef typename __alloc_traits::template
+#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+                rebind_alloc<_FF>
+#else
+                rebind_alloc<_FF>::other
+#endif
+                                                         _A;
+            _A __a(__a0);
+            typedef __allocator_destructor<_A> _D;
+            unique_ptr<__base, _D> __hold(__a.allocate(1), _D(__a, 1));
+            ::new (__hold.get()) _FF(__f, _Alloc(__a));
+            __f_ = __hold.release();
+        }
+    }
+}
+
+template<class _R>
 function<_R()>&
 function<_R()>::operator=(const function& __f)
 {
@@ -904,16 +952,15 @@
       function(_F,
                typename enable_if<!is_integral<_F>::value>::type* = 0);
 
-//     template<class _Alloc>
-//       function(allocator_arg_t, const _Alloc&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, nullptr_t);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, const function&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, function&&);
-//     template<class F, Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, F);
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, const function&);
+    template<class _F, class _Alloc>
+      function(allocator_arg_t, const _Alloc& __a, _F __f,
+               typename enable_if<!is_integral<_F>::value>::type* = 0);
 
     function& operator=(const function&);
     function& operator=(nullptr_t);
@@ -929,8 +976,9 @@
 
     // 20.7.16.2.2, function modifiers:
     void swap(function&);
-//     template<class _F, class _Alloc>
-//       void assign(_F, const _Alloc&);
+    template<class _F, class _Alloc>
+      void assign(_F __f, const _Alloc& __a)
+        {function(allocator_arg, __a, __f).swap(*this);}
 
     // 20.7.16.2.3, function capacity:
     operator bool() const {return __f_;}
@@ -968,6 +1016,21 @@
 }
 
 template<class _R, class _A0>
+template<class _Alloc>
+function<_R(_A0)>::function(allocator_arg_t, const _Alloc&, const function& __f)
+{
+    if (__f.__f_ == 0)
+        __f_ = 0;
+    else if (__f.__f_ == (const __base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__clone(__f_);
+    }
+    else
+        __f_ = __f.__f_->__clone();
+}
+
+template<class _R, class _A0>
 template <class _F>
 function<_R(_A0)>::function(_F __f,
                                      typename enable_if<!is_integral<_F>::value>::type*)
@@ -994,6 +1057,39 @@
 }
 
 template<class _R, class _A0>
+template <class _F, class _Alloc>
+function<_R(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _F __f,
+                                     typename enable_if<!is_integral<_F>::value>::type*)
+    : __f_(0)
+{
+    typedef allocator_traits<_Alloc> __alloc_traits;
+    if (__not_null(__f))
+    {
+        typedef __function::__func<_F, _Alloc, _R(_A0)> _FF;
+        if (sizeof(_FF) <= sizeof(__buf_))
+        {
+            __f_ = (__base*)&__buf_;
+            ::new (__f_) _FF(__f);
+        }
+        else
+        {
+            typedef typename __alloc_traits::template
+#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+                rebind_alloc<_FF>
+#else
+                rebind_alloc<_FF>::other
+#endif
+                                                         _A;
+            _A __a(__a0);
+            typedef __allocator_destructor<_A> _D;
+            unique_ptr<__base, _D> __hold(__a.allocate(1), _D(__a, 1));
+            ::new (__hold.get()) _FF(__f, _Alloc(__a));
+            __f_ = __hold.release();
+        }
+    }
+}
+
+template<class _R, class _A0>
 function<_R(_A0)>&
 function<_R(_A0)>::operator=(const function& __f)
 {
@@ -1148,16 +1244,15 @@
       function(_F,
                typename enable_if<!is_integral<_F>::value>::type* = 0);
 
-//     template<class _Alloc>
-//       function(allocator_arg_t, const _Alloc&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, nullptr_t);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, const function&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, function&&);
-//     template<class F, Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, F);
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, const function&);
+    template<class _F, class _Alloc>
+      function(allocator_arg_t, const _Alloc& __a, _F __f,
+               typename enable_if<!is_integral<_F>::value>::type* = 0);
 
     function& operator=(const function&);
     function& operator=(nullptr_t);
@@ -1173,8 +1268,9 @@
 
     // 20.7.16.2.2, function modifiers:
     void swap(function&);
-//     template<class _F, class _Alloc>
-//       void assign(_F, const _Alloc&);
+    template<class _F, class _Alloc>
+      void assign(_F __f, const _Alloc& __a)
+        {function(allocator_arg, __a, __f).swap(*this);}
 
     // 20.7.16.2.3, function capacity:
     operator bool() const {return __f_;}
@@ -1212,9 +1308,24 @@
 }
 
 template<class _R, class _A0, class _A1>
+template<class _Alloc>
+function<_R(_A0, _A1)>::function(allocator_arg_t, const _Alloc&, const function& __f)
+{
+    if (__f.__f_ == 0)
+        __f_ = 0;
+    else if (__f.__f_ == (const __base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__clone(__f_);
+    }
+    else
+        __f_ = __f.__f_->__clone();
+}
+
+template<class _R, class _A0, class _A1>
 template <class _F>
 function<_R(_A0, _A1)>::function(_F __f,
-                                     typename enable_if<!is_integral<_F>::value>::type*)
+                                 typename enable_if<!is_integral<_F>::value>::type*)
     : __f_(0)
 {
     if (__not_null(__f))
@@ -1238,6 +1349,39 @@
 }
 
 template<class _R, class _A0, class _A1>
+template <class _F, class _Alloc>
+function<_R(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _F __f,
+                                 typename enable_if<!is_integral<_F>::value>::type*)
+    : __f_(0)
+{
+    typedef allocator_traits<_Alloc> __alloc_traits;
+    if (__not_null(__f))
+    {
+        typedef __function::__func<_F, _Alloc, _R(_A0, _A1)> _FF;
+        if (sizeof(_FF) <= sizeof(__buf_))
+        {
+            __f_ = (__base*)&__buf_;
+            ::new (__f_) _FF(__f);
+        }
+        else
+        {
+            typedef typename __alloc_traits::template
+#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+                rebind_alloc<_FF>
+#else
+                rebind_alloc<_FF>::other
+#endif
+                                                         _A;
+            _A __a(__a0);
+            typedef __allocator_destructor<_A> _D;
+            unique_ptr<__base, _D> __hold(__a.allocate(1), _D(__a, 1));
+            ::new (__hold.get()) _FF(__f, _Alloc(__a));
+            __f_ = __hold.release();
+        }
+    }
+}
+
+template<class _R, class _A0, class _A1>
 function<_R(_A0, _A1)>&
 function<_R(_A0, _A1)>::operator=(const function& __f)
 {
@@ -1391,16 +1535,15 @@
       function(_F,
                typename enable_if<!is_integral<_F>::value>::type* = 0);
 
-//     template<class _Alloc>
-//       function(allocator_arg_t, const _Alloc&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, nullptr_t);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, const function&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, function&&);
-//     template<class F, Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, F);
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, const function&);
+    template<class _F, class _Alloc>
+      function(allocator_arg_t, const _Alloc& __a, _F __f,
+               typename enable_if<!is_integral<_F>::value>::type* = 0);
 
     function& operator=(const function&);
     function& operator=(nullptr_t);
@@ -1416,8 +1559,9 @@
 
     // 20.7.16.2.2, function modifiers:
     void swap(function&);
-//     template<class _F, class _Alloc>
-//       void assign(_F, const _Alloc&);
+    template<class _F, class _Alloc>
+      void assign(_F __f, const _Alloc& __a)
+        {function(allocator_arg, __a, __f).swap(*this);}
 
     // 20.7.16.2.3, function capacity:
     operator bool() const {return __f_;}
@@ -1455,6 +1599,22 @@
 }
 
 template<class _R, class _A0, class _A1, class _A2>
+template<class _Alloc>
+function<_R(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc&,
+                                      const function& __f)
+{
+    if (__f.__f_ == 0)
+        __f_ = 0;
+    else if (__f.__f_ == (const __base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__clone(__f_);
+    }
+    else
+        __f_ = __f.__f_->__clone();
+}
+
+template<class _R, class _A0, class _A1, class _A2>
 template <class _F>
 function<_R(_A0, _A1, _A2)>::function(_F __f,
                                      typename enable_if<!is_integral<_F>::value>::type*)
@@ -1481,6 +1641,39 @@
 }
 
 template<class _R, class _A0, class _A1, class _A2>
+template <class _F, class _Alloc>
+function<_R(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _F __f,
+                                     typename enable_if<!is_integral<_F>::value>::type*)
+    : __f_(0)
+{
+    typedef allocator_traits<_Alloc> __alloc_traits;
+    if (__not_null(__f))
+    {
+        typedef __function::__func<_F, _Alloc, _R(_A0, _A1, _A2)> _FF;
+        if (sizeof(_FF) <= sizeof(__buf_))
+        {
+            __f_ = (__base*)&__buf_;
+            ::new (__f_) _FF(__f);
+        }
+        else
+        {
+            typedef typename __alloc_traits::template
+#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+                rebind_alloc<_FF>
+#else
+                rebind_alloc<_FF>::other
+#endif
+                                                         _A;
+            _A __a(__a0);
+            typedef __allocator_destructor<_A> _D;
+            unique_ptr<__base, _D> __hold(__a.allocate(1), _D(__a, 1));
+            ::new (__hold.get()) _FF(__f, _Alloc(__a));
+            __f_ = __hold.release();
+        }
+    }
+}
+
+template<class _R, class _A0, class _A1, class _A2>
 function<_R(_A0, _A1, _A2)>&
 function<_R(_A0, _A1, _A2)>::operator=(const function& __f)
 {

Modified: libcxx/trunk/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/include/functional (original)
+++ libcxx/trunk/include/functional Fri Aug 20 14:36:46 2010
@@ -32,7 +32,7 @@
     typedef Result result_type;
 };
 
-template <ObjectType T>
+template <class T>
 class reference_wrapper
     : public unary_function<T1, R> // if wrapping a unary functor
     : public binary_function<T1, T2, R> // if wraping a binary functor
@@ -56,18 +56,17 @@
 
     // invoke
     template <class... ArgTypes>
-      requires Callable<T, ArgTypes&&...>
-        Callable<T, ArgTypes&&...>::result_type
+      typename result_of<T(ArgTypes...)>::type
           operator() (ArgTypes&&...) const;
 };
 
-template <ObjectType T> reference_wrapper<T> ref(T& t);
-template <ObjectType T> void ref(const T&& t) = delete; // LWG 688
-template <ObjectType T> reference_wrapper<T> ref(reference_wrapper<T>t);
-
-template <ObjectType T> reference_wrapper<const T> cref(const T& t);
-template <ObjectType T> void cref(const T&& t) = delete; // LWG 688
-template <ObjectType T> reference_wrapper<const T> cref(reference_wrapper<T> t);
+template <class T> reference_wrapper<T> ref(T& t);
+template <class T> void ref(const T&& t) = delete;
+template <class T> reference_wrapper<T> ref(reference_wrapper<T>t);
+
+template <class T> reference_wrapper<const T> cref(const T& t);
+template <class T> void cref(const T&& t) = delete;
+template <class T> reference_wrapper<const T> cref(reference_wrapper<T> t);
 
 template <class T>
 struct plus : binary_function<T, T, T>
@@ -187,10 +186,10 @@
 template<class T> struct is_bind_expression;
 template<class T> struct is_placeholder;
 
-template<CopyConstructible Fn, CopyConstructible... Types> 
-  unspecified bind(Fn, Types...);
-template<Returnable R, CopyConstructible Fn, CopyConstructible... Types> 
-  unspecified bind(Fn, Types...);
+template<class Fn, class... BoundArgs> 
+  unspecified bind(Fn&&, BoundArgs&&...);
+template<class R, class Fn, class... BoundArgs> 
+  unspecified bind(Fn&&, BoundArgs&&...);
 
 namespace placeholders { 
   // M is the implementation-defined number of placeholders 
@@ -334,24 +333,28 @@
 template <class S, class T>          const_mem_fun_ref_t<S,T>    mem_fun_ref(S (T::*f)() const);
 template <class S, class T, class A> const_mem_fun1_ref_t<S,T,A> mem_fun_ref(S (T::*f)(A) const);
 
+template<class R, class T> unspecified mem_fn(R T::*);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...));
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) volatile);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const volatile);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) &);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const &);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) volatile &);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const volatile &);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) &&);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const &&);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) volatile &&);
+template<class R, class T, class... Args> unspecified mem_fn(R (T::*)(Args...) const volatile &&);
+
 class bad_function_call
     : public exception
 {
 };
 
-template<Returnable R, class T> unspecified mem_fn(R T::* pm);
-template<Returnable R, class T, CopyConstructible... Args> 
-  unspecified mem_fn(R (T::* pm)(Args...));
-template<Returnable R, class T, CopyConstructible... Args> 
-  unspecified mem_fn(R (T::* pm)(Args...) const);
-template<Returnable R, class T, CopyConstructible... Args> 
-  unspecified mem_fn(R (T::* pm)(Args...) volatile);
-template<Returnable R, class T, CopyConstructible... Args> 
-  unspecified mem_fn(R (T::* pm)(Args...) const volatile);
+template<class> class function; // undefined
 
-template<FunctionType> class function; // undefined
-
-template<Returnable R, CopyConstructible... ArgTypes>
+template<class R, class... ArgTypes>
 class function<R(ArgTypes...)>
   : public unary_function<T1, R>      // iff sizeof...(ArgTypes) == 1 and
                                       // ArgTypes contains T1
@@ -361,19 +364,13 @@
 public:
     typedef R result_type;
 
-    // 20.7.16.2.1, construct/copy/destroy:
-    explicit function();
+    // construct/copy/destroy:
+    function();
     function(nullptr_t);
     function(const function&);
     function(function&&);
     template<class F>
-      requires CopyConstructible<F> && Callable<F, ArgTypes...>
-            && Convertible<Callable<F, ArgTypes...>::result_type, R>
       function(F);
-//     template<class F>
-//       requires CopyConstructible<F> && Callable<F, ArgTypes...>
-//             && Convertible<Callable<F, ArgTypes...>::result_type, R>
-//       function(F&&);
     template<Allocator Alloc>
       function(allocator_arg_t, const Alloc&);
     template<Allocator Alloc>
@@ -384,35 +381,23 @@
       function(allocator_arg_t, const Alloc&, function&&);
     template<class F, Allocator Alloc>
       function(allocator_arg_t, const Alloc&, F);
-//     template<class F, Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, F&&);
 
     function& operator=(const function&);
     function& operator=(function&&);
     function& operator=(nullptr_t);
     template<class F>
-      requires CopyConstructible<F> && Callable<F, ArgTypes..>
-            && Convertible<Callable<F, ArgTypes...>::result_type
-      function& operator=(F);
-//     template<class F>
-//       requires CopyConstructible<F> && Callable<F, ArgTypes...>
-//             && Convertible<Callable<F, ArgTypes...>::result_type, R>
-//       function& operator=(F&&);
+      function& operator=(F&&);
     template<class F>
-      requires Callable<F, ArgTypes...>
-            && Convertible<Callable<F, ArgTypes...>::result_type, R>
       function& operator=(reference_wrapper<F>);
 
     ~function();
 
-    // 20.7.16.2.2, function modifiers:
+    // function modifiers:
     void swap(function&);
-    template<class F, Allocator Alloc>
-      requires Callable<F, ArgTypes...>
-            && Convertible<Callable<F, ArgTypes...>::result_type, R>
-      void assign(F, const Alloc&);
+    template<class F, class Alloc>
+      void assign(F&&, const Alloc&);
 
-    // 20.7.16.2.3, function capacity:
+    // function capacity:
     explicit operator bool() const;
 
     // deleted overloads close possible hole in the type system
@@ -421,36 +406,30 @@
     template<class R2, class... ArgTypes2>
       bool operator!=(const function<R2(ArgTypes2...)>&) = delete;
 
-    // 20.7.16.2.4, function invocation:
+    // function invocation:
     R operator()(ArgTypes...) const;
 
-    // 20.7.16.2.5, function target access:
+    // function target access:
     const std::type_info& target_type() const;
-    template <typename T>
-      requires Callable<T, ArgTypes...>
-            && Convertible<Callable<T, ArgTypes...>::result_type, R>
-      T* target();
-    template <typename T>
-      requires Callable<T, ArgTypes...>
-            && Convertible<Callable<T, ArgTypes...>::result_type, R>
-      const T* target() const;
+    template <typename T>       T* target();
+    template <typename T> const T* target() const;
 };
 
-// 20.7.16.2.6, Null pointer comparisons: 
-template <MoveConstructible R, MoveConstructible ... ArgTypes> 
+// Null pointer comparisons: 
+template <class R, class ... ArgTypes> 
   bool operator==(const function<R(ArgTypes...)>&, nullptr_t);
 
-template <MoveConstructible R, MoveConstructible ... ArgTypes> 
+template <class R, class ... ArgTypes> 
   bool operator==(nullptr_t, const function<R(ArgTypes...)>&);
 
-template <MoveConstructible R, MoveConstructible ... ArgTypes> 
+template <class R, class ... ArgTypes> 
   bool operator!=(const function<R(ArgTypes...)>&, nullptr_t);
 
-template <MoveConstructible  R, MoveConstructible ... ArgTypes> 
+template <class  R, class ... ArgTypes> 
   bool operator!=(nullptr_t, const function<R(ArgTypes...)>&);
 
-// 20.7.16.2.7, specialized algorithms: 
-template <MoveConstructible  R, MoveConstructible ... ArgTypes> 
+// specialized algorithms: 
+template <class  R, class ... ArgTypes> 
   void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&);
 
 template <class T> struct hash;
@@ -1118,27 +1097,26 @@
 public:
     typedef _R result_type;
 
-    // 20.7.16.2.1, construct/copy/destroy:
+    // construct/copy/destroy:
     function() : __f_(0) {}
     function(nullptr_t) : __f_(0) {}
     function(const function&);
-#ifdef _LIBCPP_MOVE
     function(function&&);
-#endif
     template<class _F>
       function(_F,
                typename enable_if<!is_integral<_F>::value>::type* = 0);
 
-//     template<class _Alloc>
-//       function(allocator_arg_t, const _Alloc&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, nullptr_t);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, const function&);
-//     template<Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, function&&);
-//     template<class F, Allocator Alloc>
-//       function(allocator_arg_t, const Alloc&, F);
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {}
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, const function&);
+    template<class _Alloc>
+      function(allocator_arg_t, const _Alloc&, function&&);
+    template<class _F, class _Alloc>
+      function(allocator_arg_t, const _Alloc& __a, _F __f,
+               typename enable_if<!is_integral<_F>::value>::type* = 0);
 
     function& operator=(const function&);
     function& operator=(function&&);
@@ -1153,26 +1131,26 @@
 
     ~function();
 
-    // 20.7.16.2.2, function modifiers:
+    // function modifiers:
     void swap(function&);
-//     template<class _F, class _Alloc>
-//       void assign(_F, const _Alloc&);
+    template<class _F, class _Alloc>
+      void assign(_F&& __f, const _Alloc& __a)
+        {function(allocator_arg, __a, _STD::forward<_F>(__f)).swap(*this);}
 
-    // 20.7.16.2.3, function capacity:
+    // function capacity:
     /*explicit*/ operator bool() const {return __f_;}
 
-private:
     // deleted overloads close possible hole in the type system
     template<class _R2, class... _ArgTypes2>
-      bool operator==(const function<_R2(_ArgTypes2...)>&);// = delete;
+      bool operator==(const function<_R2(_ArgTypes2...)>&) = delete;
     template<class _R2, class... _ArgTypes2>
-      bool operator!=(const function<_R2(_ArgTypes2...)>&);// = delete;
+      bool operator!=(const function<_R2(_ArgTypes2...)>&) = delete;
 public:
-    // 20.7.16.2.4, function invocation:
+    // function invocation:
     _R operator()(_ArgTypes...) const;
 
 #ifndef _LIBCPP_NO_RTTI
-    // 20.7.16.2.5, function target access:
+    // function target access:
     const std::type_info& target_type() const;
     template <typename _T> _T* target();
     template <typename _T> const _T* target() const;
@@ -1194,6 +1172,22 @@
 }
 
 template<class _R, class ..._ArgTypes>
+template <class _Alloc>
+function<_R(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&,
+                                     const function& __f)
+{
+    if (__f.__f_ == 0)
+        __f_ = 0;
+    else if (__f.__f_ == (const __base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__clone(__f_);
+    }
+    else
+        __f_ = __f.__f_->__clone();
+}
+
+template<class _R, class ..._ArgTypes>
 function<_R(_ArgTypes...)>::function(function&& __f)
 {
     if (__f.__f_ == 0)
@@ -1211,6 +1205,25 @@
 }
 
 template<class _R, class ..._ArgTypes>
+template <class _Alloc>
+function<_R(_ArgTypes...)>::function(allocator_arg_t, const _Alloc&,
+                                     function&& __f)
+{
+    if (__f.__f_ == 0)
+        __f_ = 0;
+    else if (__f.__f_ == (__base*)&__f.__buf_)
+    {
+        __f_ = (__base*)&__buf_;
+        __f.__f_->__clone(__f_);
+    }
+    else
+    {
+        __f_ = __f.__f_;
+        __f.__f_ = 0;
+    }
+}
+
+template<class _R, class ..._ArgTypes>
 template <class _F>
 function<_R(_ArgTypes...)>::function(_F __f,
                                      typename enable_if<!is_integral<_F>::value>::type*)
@@ -1237,6 +1250,39 @@
 }
 
 template<class _R, class ..._ArgTypes>
+template <class _F, class _Alloc>
+function<_R(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a0, _F __f,
+                                     typename enable_if<!is_integral<_F>::value>::type*)
+    : __f_(0)
+{
+    typedef allocator_traits<_Alloc> __alloc_traits;
+    if (__not_null(__f))
+    {
+        typedef __function::__func<_F, _Alloc, _R(_ArgTypes...)> _FF;
+        if (sizeof(_FF) <= sizeof(__buf_))
+        {
+            __f_ = (__base*)&__buf_;
+            ::new (__f_) _FF(_STD::move(__f));
+        }
+        else
+        {
+            typedef typename __alloc_traits::template
+#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
+                rebind_alloc<_FF>
+#else
+                rebind_alloc<_FF>::other
+#endif
+                                                         _A;
+            _A __a(__a0);
+            typedef __allocator_destructor<_A> _D;
+            unique_ptr<__base, _D> __hold(__a.allocate(1), _D(__a, 1));
+            ::new (__hold.get()) _FF(_STD::move(__f), _Alloc(__a));
+            __f_ = __hold.release();
+        }
+    }
+}
+
+template<class _R, class ..._ArgTypes>
 function<_R(_ArgTypes...)>&
 function<_R(_ArgTypes...)>::operator=(const function& __f)
 {

Modified: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp Fri Aug 20 14:36:46 2010
@@ -16,7 +16,10 @@
 #include <functional>
 #include <cassert>
 
+#include "../test_allocator.h"
+
 int main()
 {
-#error template<class A> function(allocator_arg_t, const A&); not implemented
+    std::function<int(int)> f(std::allocator_arg, test_allocator<int>());
+    assert(!f);
 }

Modified: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp Fri Aug 20 14:36:46 2010
@@ -16,7 +16,65 @@
 #include <functional>
 #include <cassert>
 
+#include "../test_allocator.h"
+
+class A
+{
+    int data_[10];
+public:
+    static int count;
+
+    A()
+    {
+        ++count;
+        for (int i = 0; i < 10; ++i)
+            data_[i] = i;
+    }
+
+    A(const A&) {++count;}
+
+    ~A() {--count;}
+
+    int operator()(int i) const
+    {
+        for (int j = 0; j < 10; ++j)
+            i += data_[j];
+        return i;
+    }
+
+    int foo(int) const {return 1;}
+};
+
+int A::count = 0;
+
+int g(int) {return 0;}
+
 int main()
 {
-#error template<class F, class A> function(allocator_arg_t, const A&, F); not implemented
+    {
+    std::function<int(int)> f(std::allocator_arg, test_allocator<A>(), A());
+    assert(A::count == 1);
+    assert(f.target<A>());
+    assert(f.target<int(*)(int)>() == 0);
+    }
+    assert(A::count == 0);
+    {
+    std::function<int(int)> f(std::allocator_arg, test_allocator<int(*)(int)>(), g);
+    assert(f.target<int(*)(int)>());
+    assert(f.target<A>() == 0);
+    }
+    {
+    std::function<int(int)> f(std::allocator_arg, test_allocator<int(*)(int)>(),
+                              (int (*)(int))0);
+    assert(!f);
+    assert(f.target<int(*)(int)>() == 0);
+    assert(f.target<A>() == 0);
+    }
+    {
+    std::function<int(const A*, int)> f(std::allocator_arg,
+                                        test_allocator<int(A::*)(int)const>(),
+                                        &A::foo);
+    assert(f);
+    assert(f.target<int (A::*)(int) const>() != 0);
+    }
 }

Modified: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp Fri Aug 20 14:36:46 2010
@@ -14,9 +14,91 @@
 // template<class A> function(allocator_arg_t, const A&, const function&);
 
 #include <functional>
+#include <new>
+#include <cstdlib>
 #include <cassert>
 
+#include "../test_allocator.h"
+
+int new_called = 0;
+
+void* operator new(std::size_t s) throw(std::bad_alloc)
+{
+    ++new_called;
+    return std::malloc(s);
+}
+
+void  operator delete(void* p) throw()
+{
+    --new_called;
+    std::free(p);
+}
+
+class A
+{
+    int data_[10];
+public:
+    static int count;
+
+    A()
+    {
+        ++count;
+        for (int i = 0; i < 10; ++i)
+            data_[i] = i;
+    }
+
+    A(const A&) {++count;}
+
+    ~A() {--count;}
+
+    int operator()(int i) const
+    {
+        for (int j = 0; j < 10; ++j)
+            i += data_[j];
+        return i;
+    }
+};
+
+int A::count = 0;
+
+int g(int) {return 0;}
+
 int main()
 {
-#error template<class A> function(allocator_arg_t, const A&, const function&); not implemented
+    assert(new_called == 0);
+    {
+    std::function<int(int)> f = A();
+    assert(A::count == 1);
+    assert(new_called == 1);
+    assert(f.target<A>());
+    assert(f.target<int(*)(int)>() == 0);
+    std::function<int(int)> f2(std::allocator_arg, test_allocator<A>(), f);
+    assert(A::count == 2);
+    assert(new_called == 2);
+    assert(f2.target<A>());
+    assert(f2.target<int(*)(int)>() == 0);
+    }
+    assert(A::count == 0);
+    assert(new_called == 0);
+    {
+    std::function<int(int)> f = g;
+    assert(new_called == 0);
+    assert(f.target<int(*)(int)>());
+    assert(f.target<A>() == 0);
+    std::function<int(int)> f2(std::allocator_arg, test_allocator<int(*)(int)>(), f);
+    assert(new_called == 0);
+    assert(f2.target<int(*)(int)>());
+    assert(f2.target<A>() == 0);
+    }
+    assert(new_called == 0);
+    {
+    std::function<int(int)> f;
+    assert(new_called == 0);
+    assert(f.target<int(*)(int)>() == 0);
+    assert(f.target<A>() == 0);
+    std::function<int(int)> f2(std::allocator_arg, test_allocator<int>(), f);
+    assert(new_called == 0);
+    assert(f2.target<int(*)(int)>() == 0);
+    assert(f2.target<A>() == 0);
+    }
 }

Modified: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp Fri Aug 20 14:36:46 2010
@@ -16,7 +16,10 @@
 #include <functional>
 #include <cassert>
 
+#include "../test_allocator.h"
+
 int main()
 {
-#error template<class A> function(allocator_arg_t, const A&, nullptr_t); not implemented
+    std::function<int(int)> f(std::allocator_arg, test_allocator<int>(), nullptr);
+    assert(!f);
 }

Modified: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp Fri Aug 20 14:36:46 2010
@@ -16,7 +16,66 @@
 #include <functional>
 #include <cassert>
 
+#include "../test_allocator.h"
+
+int new_called = 0;
+
+void* operator new(std::size_t s) throw(std::bad_alloc)
+{
+    ++new_called;
+    return std::malloc(s);
+}
+
+void  operator delete(void* p) throw()
+{
+    --new_called;
+    std::free(p);
+}
+
+class A
+{
+    int data_[10];
+public:
+    static int count;
+
+    A()
+    {
+        ++count;
+        for (int i = 0; i < 10; ++i)
+            data_[i] = i;
+    }
+
+    A(const A&) {++count;}
+
+    ~A() {--count;}
+
+    int operator()(int i) const
+    {
+        for (int j = 0; j < 10; ++j)
+            i += data_[j];
+        return i;
+    }
+};
+
+int A::count = 0;
+
 int main()
 {
-#error template<class A> function(allocator_arg_t, const A&, function&&); not implemented
+#ifdef _LIBCPP_MOVE
+    assert(new_called == 0);
+    {
+    std::function<int(int)> f = A();
+    assert(A::count == 1);
+    assert(new_called == 1);
+    assert(f.target<A>());
+    assert(f.target<int(*)(int)>() == 0);
+    std::function<int(int)> f2(std::allocator_arg, test_allocator<A>(), std::move(f));
+    assert(A::count == 1);
+    assert(new_called == 1);
+    assert(f2.target<A>());
+    assert(f2.target<int(*)(int)>() == 0);
+    assert(f.target<A>() == 0);
+    assert(f.target<int(*)(int)>() == 0);
+    }
+#endif
 }

Modified: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp?rev=111672&r1=111671&r2=111672&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp Fri Aug 20 14:36:46 2010
@@ -16,7 +16,45 @@
 #include <functional>
 #include <cassert>
 
+#include "../test_allocator.h"
+
+class A
+{
+    int data_[10];
+public:
+    static int count;
+
+    A()
+    {
+        ++count;
+        for (int i = 0; i < 10; ++i)
+            data_[i] = i;
+    }
+
+    A(const A&) {++count;}
+
+    ~A() {--count;}
+
+    int operator()(int i) const
+    {
+        for (int j = 0; j < 10; ++j)
+            i += data_[j];
+        return i;
+    }
+
+    int foo(int) const {return 1;}
+};
+
+int A::count = 0;
+
 int main()
 {
-#error template<class F, class A> void assign(F&&, const A&); not implemented
+    {
+    std::function<int(int)> f;
+    f.assign(A(), test_allocator<A>());
+    assert(A::count == 1);
+    assert(f.target<A>());
+    assert(f.target<int(*)(int)>() == 0);
+    }
+    assert(A::count == 0);
 }

Added: libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h?rev=111672&view=auto
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h (added)
+++ libcxx/trunk/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h Fri Aug 20 14:36:46 2010
@@ -0,0 +1,112 @@
+#ifndef TEST_ALLOCATOR_H
+#define TEST_ALLOCATOR_H
+
+#include <cstddef>
+#include <type_traits>
+#include <cstdlib>
+#include <new>
+#include <climits>
+
+class test_alloc_base
+{
+protected:
+    static int count;
+public:
+    static int throw_after;
+};
+
+int test_alloc_base::count = 0;
+int test_alloc_base::throw_after = INT_MAX;
+
+template <class T>
+class test_allocator
+    : public test_alloc_base
+{
+    int data_;
+
+    template <class U> friend class test_allocator;
+public:
+
+    typedef unsigned                                                   size_type;
+    typedef int                                                        difference_type;
+    typedef T                                                          value_type;
+    typedef value_type*                                                pointer;
+    typedef const value_type*                                          const_pointer;
+    typedef typename std::add_lvalue_reference<value_type>::type       reference;
+    typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
+
+    template <class U> struct rebind {typedef test_allocator<U> other;};
+
+    test_allocator() throw() : data_(-1) {}
+    explicit test_allocator(int i) throw() : data_(i) {}
+    test_allocator(const test_allocator& a) throw()
+        : data_(a.data_) {}
+    template <class U> test_allocator(const test_allocator<U>& a) throw()
+        : data_(a.data_) {}
+    ~test_allocator() throw() {data_ = 0;}
+    pointer address(reference x) const {return &x;}
+    const_pointer address(const_reference x) const {return &x;}
+    pointer allocate(size_type n, const void* = 0)
+        {
+            if (count >= throw_after)
+                throw std::bad_alloc();
+            ++count;
+            return (pointer)std::malloc(n * sizeof(T));
+        }
+    void deallocate(pointer p, size_type n)
+        {std::free(p);}
+    size_type max_size() const throw()
+        {return UINT_MAX / sizeof(T);}
+    void construct(pointer p, const T& val)
+        {::new(p) T(val);}
+#ifdef _LIBCPP_MOVE
+    void construct(pointer p, T&& val)
+        {::new(p) T(std::move(val));}
+#endif
+    void destroy(pointer p) {p->~T();}
+
+    friend bool operator==(const test_allocator& x, const test_allocator& y)
+        {return x.data_ == y.data_;}
+    friend bool operator!=(const test_allocator& x, const test_allocator& y)
+        {return !(x == y);}
+};
+
+template <class T>
+class other_allocator
+{
+    int data_;
+
+    template <class U> friend class other_allocator;
+
+public:
+    typedef T value_type;
+
+    other_allocator() : data_(-1) {}
+    explicit other_allocator(int i) : data_(i) {}
+    template <class U> other_allocator(const other_allocator<U>& a)
+        : data_(a.data_) {}
+    T* allocate(std::size_t n)
+        {return (T*)std::malloc(n * sizeof(T));}
+    void deallocate(T* p, std::size_t n)
+        {std::free(p);}
+
+    other_allocator select_on_container_copy_construction() const
+        {return other_allocator(-2);}
+
+    friend bool operator==(const other_allocator& x, const other_allocator& y)
+        {return x.data_ == y.data_;}
+    friend bool operator!=(const other_allocator& x, const other_allocator& y)
+        {return !(x == y);}
+
+    typedef std::true_type propagate_on_container_copy_assignment;
+    typedef std::true_type propagate_on_container_move_assignment;
+    typedef std::true_type propagate_on_container_swap;
+
+#ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE
+    std::size_t max_size() const
+        {return UINT_MAX / sizeof(T);}
+#endif
+
+};
+
+#endif





More information about the cfe-commits mailing list