From 725528086c5850ad2340d192c16cd39e1143a8cf Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Fri, 20 Aug 2010 19:36:46 +0000 Subject: [PATCH] Installed allocator into std::function git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@111672 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__functional_03 | 293 +++++++++++++++--- include/functional | 224 +++++++------ .../func.wrap.func.con/alloc.pass.cpp | 5 +- .../func.wrap.func.con/alloc_F.pass.cpp | 60 +++- .../alloc_function.pass.cpp | 84 ++++- .../func.wrap.func.con/alloc_nullptr.pass.cpp | 5 +- .../alloc_rfunction.pass.cpp | 61 +++- .../assign_F_alloc.pass.cpp | 40 ++- .../func.wrap/func.wrap.func/test_allocator.h | 112 +++++++ 9 files changed, 739 insertions(+), 145 deletions(-) create mode 100644 test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h diff --git a/include/__functional_03 b/include/__functional_03 index fa318df1..f2880adc 100644 --- a/include/__functional_03 +++ b/include/__functional_03 @@ -367,7 +367,7 @@ template _R __func<_F, _Alloc, _R()>::operator()() { - return __invoke<_R>(__f_.first()); + return __invoke(__f_.first()); } #ifndef _LIBCPP_NO_RTTI @@ -660,16 +660,15 @@ public: function(_F, typename enable_if::value>::type* = 0); -// template -// function(allocator_arg_t, const _Alloc&); -// template -// function(allocator_arg_t, const Alloc&, nullptr_t); -// template -// function(allocator_arg_t, const Alloc&, const function&); -// template -// function(allocator_arg_t, const Alloc&, function&&); -// template -// function(allocator_arg_t, const Alloc&, F); + template + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _F __f, + typename enable_if::value>::type* = 0); function& operator=(const function&); function& operator=(nullptr_t); @@ -685,8 +684,9 @@ public: // 20.7.16.2.2, function modifiers: void swap(function&); -// template -// void assign(_F, const _Alloc&); + template + 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_;} @@ -723,6 +723,21 @@ function<_R()>::function(const function& __f) __f_ = __f.__f_->__clone(); } +template +template +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 template function<_R()>::function(_F __f, @@ -749,6 +764,39 @@ function<_R()>::function(_F __f, } } +template +template +function<_R()>::function(allocator_arg_t, const _Alloc& __a0, _F __f, + typename enable_if::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 function<_R()>& function<_R()>::operator=(const function& __f) @@ -904,16 +952,15 @@ public: function(_F, typename enable_if::value>::type* = 0); -// template -// function(allocator_arg_t, const _Alloc&); -// template -// function(allocator_arg_t, const Alloc&, nullptr_t); -// template -// function(allocator_arg_t, const Alloc&, const function&); -// template -// function(allocator_arg_t, const Alloc&, function&&); -// template -// function(allocator_arg_t, const Alloc&, F); + template + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _F __f, + typename enable_if::value>::type* = 0); function& operator=(const function&); function& operator=(nullptr_t); @@ -929,8 +976,9 @@ public: // 20.7.16.2.2, function modifiers: void swap(function&); -// template -// void assign(_F, const _Alloc&); + template + 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_;} @@ -967,6 +1015,21 @@ function<_R(_A0)>::function(const function& __f) __f_ = __f.__f_->__clone(); } +template +template +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 template function<_R(_A0)>::function(_F __f, @@ -993,6 +1056,39 @@ function<_R(_A0)>::function(_F __f, } } +template +template +function<_R(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _F __f, + typename enable_if::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 function<_R(_A0)>& function<_R(_A0)>::operator=(const function& __f) @@ -1148,16 +1244,15 @@ public: function(_F, typename enable_if::value>::type* = 0); -// template -// function(allocator_arg_t, const _Alloc&); -// template -// function(allocator_arg_t, const Alloc&, nullptr_t); -// template -// function(allocator_arg_t, const Alloc&, const function&); -// template -// function(allocator_arg_t, const Alloc&, function&&); -// template -// function(allocator_arg_t, const Alloc&, F); + template + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _F __f, + typename enable_if::value>::type* = 0); function& operator=(const function&); function& operator=(nullptr_t); @@ -1173,8 +1268,9 @@ public: // 20.7.16.2.2, function modifiers: void swap(function&); -// template -// void assign(_F, const _Alloc&); + template + 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_;} @@ -1211,10 +1307,25 @@ function<_R(_A0, _A1)>::function(const function& __f) __f_ = __f.__f_->__clone(); } +template +template +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 template function<_R(_A0, _A1)>::function(_F __f, - typename enable_if::value>::type*) + typename enable_if::value>::type*) : __f_(0) { if (__not_null(__f)) @@ -1237,6 +1348,39 @@ function<_R(_A0, _A1)>::function(_F __f, } } +template +template +function<_R(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _F __f, + typename enable_if::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 function<_R(_A0, _A1)>& function<_R(_A0, _A1)>::operator=(const function& __f) @@ -1391,16 +1535,15 @@ public: function(_F, typename enable_if::value>::type* = 0); -// template -// function(allocator_arg_t, const _Alloc&); -// template -// function(allocator_arg_t, const Alloc&, nullptr_t); -// template -// function(allocator_arg_t, const Alloc&, const function&); -// template -// function(allocator_arg_t, const Alloc&, function&&); -// template -// function(allocator_arg_t, const Alloc&, F); + template + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _F __f, + typename enable_if::value>::type* = 0); function& operator=(const function&); function& operator=(nullptr_t); @@ -1416,8 +1559,9 @@ public: // 20.7.16.2.2, function modifiers: void swap(function&); -// template -// void assign(_F, const _Alloc&); + template + 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_;} @@ -1454,6 +1598,22 @@ function<_R(_A0, _A1, _A2)>::function(const function& __f) __f_ = __f.__f_->__clone(); } +template +template +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 template function<_R(_A0, _A1, _A2)>::function(_F __f, @@ -1480,6 +1640,39 @@ function<_R(_A0, _A1, _A2)>::function(_F __f, } } +template +template +function<_R(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _F __f, + typename enable_if::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 function<_R(_A0, _A1, _A2)>& function<_R(_A0, _A1, _A2)>::operator=(const function& __f) diff --git a/include/functional b/include/functional index 55c38e5a..30063f40 100644 --- a/include/functional +++ b/include/functional @@ -32,7 +32,7 @@ struct binary_function typedef Result result_type; }; -template +template class reference_wrapper : public unary_function // if wrapping a unary functor : public binary_function // if wraping a binary functor @@ -56,18 +56,17 @@ public: // invoke template - requires Callable - Callable::result_type + typename result_of::type operator() (ArgTypes&&...) const; }; -template reference_wrapper ref(T& t); -template void ref(const T&& t) = delete; // LWG 688 -template reference_wrapper ref(reference_wrappert); +template reference_wrapper ref(T& t); +template void ref(const T&& t) = delete; +template reference_wrapper ref(reference_wrappert); -template reference_wrapper cref(const T& t); -template void cref(const T&& t) = delete; // LWG 688 -template reference_wrapper cref(reference_wrapper t); +template reference_wrapper cref(const T& t); +template void cref(const T&& t) = delete; +template reference_wrapper cref(reference_wrapper t); template struct plus : binary_function @@ -187,10 +186,10 @@ template binary_negate not2(const Predicate& pred); template struct is_bind_expression; template struct is_placeholder; -template - unspecified bind(Fn, Types...); -template - unspecified bind(Fn, Types...); +template + unspecified bind(Fn&&, BoundArgs&&...); +template + unspecified bind(Fn&&, BoundArgs&&...); namespace placeholders { // M is the implementation-defined number of placeholders @@ -334,24 +333,28 @@ public: template const_mem_fun_ref_t mem_fun_ref(S (T::*f)() const); template const_mem_fun1_ref_t mem_fun_ref(S (T::*f)(A) const); +template unspecified mem_fn(R T::*); +template unspecified mem_fn(R (T::*)(Args...)); +template unspecified mem_fn(R (T::*)(Args...) const); +template unspecified mem_fn(R (T::*)(Args...) volatile); +template unspecified mem_fn(R (T::*)(Args...) const volatile); +template unspecified mem_fn(R (T::*)(Args...) &); +template unspecified mem_fn(R (T::*)(Args...) const &); +template unspecified mem_fn(R (T::*)(Args...) volatile &); +template unspecified mem_fn(R (T::*)(Args...) const volatile &); +template unspecified mem_fn(R (T::*)(Args...) &&); +template unspecified mem_fn(R (T::*)(Args...) const &&); +template unspecified mem_fn(R (T::*)(Args...) volatile &&); +template unspecified mem_fn(R (T::*)(Args...) const volatile &&); + class bad_function_call : public exception { }; -template unspecified mem_fn(R T::* pm); -template - unspecified mem_fn(R (T::* pm)(Args...)); -template - unspecified mem_fn(R (T::* pm)(Args...) const); -template - unspecified mem_fn(R (T::* pm)(Args...) volatile); -template - unspecified mem_fn(R (T::* pm)(Args...) const volatile); +template class function; // undefined -template class function; // undefined - -template +template class function : public unary_function // iff sizeof...(ArgTypes) == 1 and // ArgTypes contains T1 @@ -361,19 +364,13 @@ class function 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 - requires CopyConstructible && Callable - && Convertible::result_type, R> function(F); -// template -// requires CopyConstructible && Callable -// && Convertible::result_type, R> -// function(F&&); template function(allocator_arg_t, const Alloc&); template @@ -384,35 +381,23 @@ public: function(allocator_arg_t, const Alloc&, function&&); template function(allocator_arg_t, const Alloc&, F); -// template -// function(allocator_arg_t, const Alloc&, F&&); function& operator=(const function&); function& operator=(function&&); function& operator=(nullptr_t); template - requires CopyConstructible && Callable - && Convertible::result_type - function& operator=(F); -// template -// requires CopyConstructible && Callable -// && Convertible::result_type, R> -// function& operator=(F&&); + function& operator=(F&&); template - requires Callable - && Convertible::result_type, R> function& operator=(reference_wrapper); ~function(); - // 20.7.16.2.2, function modifiers: + // function modifiers: void swap(function&); - template - requires Callable - && Convertible::result_type, R> - void assign(F, const Alloc&); + template + 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 @@ public: template bool operator!=(const function&) = 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 - requires Callable - && Convertible::result_type, R> - T* target(); - template - requires Callable - && Convertible::result_type, R> - const T* target() const; + template T* target(); + template const T* target() const; }; -// 20.7.16.2.6, Null pointer comparisons: -template +// Null pointer comparisons: +template bool operator==(const function&, nullptr_t); -template +template bool operator==(nullptr_t, const function&); -template +template bool operator!=(const function&, nullptr_t); -template +template bool operator!=(nullptr_t, const function&); -// 20.7.16.2.7, specialized algorithms: -template +// specialized algorithms: +template void swap(function&, function&); template struct hash; @@ -1118,27 +1097,26 @@ class function<_R(_ArgTypes...)> 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 function(_F, typename enable_if::value>::type* = 0); -// template -// function(allocator_arg_t, const _Alloc&); -// template -// function(allocator_arg_t, const Alloc&, nullptr_t); -// template -// function(allocator_arg_t, const Alloc&, const function&); -// template -// function(allocator_arg_t, const Alloc&, function&&); -// template -// function(allocator_arg_t, const Alloc&, F); + template + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc&, function&&); + template + function(allocator_arg_t, const _Alloc& __a, _F __f, + typename enable_if::value>::type* = 0); function& operator=(const function&); function& operator=(function&&); @@ -1153,26 +1131,26 @@ public: ~function(); - // 20.7.16.2.2, function modifiers: + // function modifiers: void swap(function&); -// template -// void assign(_F, const _Alloc&); + template + 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 - bool operator==(const function<_R2(_ArgTypes2...)>&);// = delete; + bool operator==(const function<_R2(_ArgTypes2...)>&) = delete; template - 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 _T* target(); template const _T* target() const; @@ -1193,6 +1171,22 @@ function<_R(_ArgTypes...)>::function(const function& __f) __f_ = __f.__f_->__clone(); } +template +template +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 function<_R(_ArgTypes...)>::function(function&& __f) { @@ -1210,6 +1204,25 @@ function<_R(_ArgTypes...)>::function(function&& __f) } } +template +template +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 template function<_R(_ArgTypes...)>::function(_F __f, @@ -1236,6 +1249,39 @@ function<_R(_ArgTypes...)>::function(_F __f, } } +template +template +function<_R(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a0, _F __f, + typename enable_if::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 function<_R(_ArgTypes...)>& function<_R(_ArgTypes...)>::operator=(const function& __f) diff --git a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp index c6628718..fa65aae8 100644 --- a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp +++ b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc.pass.cpp @@ -16,7 +16,10 @@ #include #include +#include "../test_allocator.h" + int main() { -#error template function(allocator_arg_t, const A&); not implemented + std::function f(std::allocator_arg, test_allocator()); + assert(!f); } diff --git a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp index 01ffad74..43868e39 100644 --- a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp +++ b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp @@ -16,7 +16,65 @@ #include #include +#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 function(allocator_arg_t, const A&, F); not implemented + { + std::function f(std::allocator_arg, test_allocator(), A()); + assert(A::count == 1); + assert(f.target()); + assert(f.target() == 0); + } + assert(A::count == 0); + { + std::function f(std::allocator_arg, test_allocator(), g); + assert(f.target()); + assert(f.target() == 0); + } + { + std::function f(std::allocator_arg, test_allocator(), + (int (*)(int))0); + assert(!f); + assert(f.target() == 0); + assert(f.target() == 0); + } + { + std::function f(std::allocator_arg, + test_allocator(), + &A::foo); + assert(f); + assert(f.target() != 0); + } } diff --git a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp index 893949cc..561dd683 100644 --- a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp +++ b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp @@ -14,9 +14,91 @@ // template function(allocator_arg_t, const A&, const function&); #include +#include +#include #include +#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 function(allocator_arg_t, const A&, const function&); not implemented + assert(new_called == 0); + { + std::function f = A(); + assert(A::count == 1); + assert(new_called == 1); + assert(f.target()); + assert(f.target() == 0); + std::function f2(std::allocator_arg, test_allocator(), f); + assert(A::count == 2); + assert(new_called == 2); + assert(f2.target()); + assert(f2.target() == 0); + } + assert(A::count == 0); + assert(new_called == 0); + { + std::function f = g; + assert(new_called == 0); + assert(f.target()); + assert(f.target() == 0); + std::function f2(std::allocator_arg, test_allocator(), f); + assert(new_called == 0); + assert(f2.target()); + assert(f2.target() == 0); + } + assert(new_called == 0); + { + std::function f; + assert(new_called == 0); + assert(f.target() == 0); + assert(f.target() == 0); + std::function f2(std::allocator_arg, test_allocator(), f); + assert(new_called == 0); + assert(f2.target() == 0); + assert(f2.target() == 0); + } } diff --git a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp index 048b7f6b..f69a9c61 100644 --- a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp +++ b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_nullptr.pass.cpp @@ -16,7 +16,10 @@ #include #include +#include "../test_allocator.h" + int main() { -#error template function(allocator_arg_t, const A&, nullptr_t); not implemented + std::function f(std::allocator_arg, test_allocator(), nullptr); + assert(!f); } diff --git a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp index 15e4dad2..263cd81a 100644 --- a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp +++ b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_rfunction.pass.cpp @@ -16,7 +16,66 @@ #include #include +#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 function(allocator_arg_t, const A&, function&&); not implemented +#ifdef _LIBCPP_MOVE + assert(new_called == 0); + { + std::function f = A(); + assert(A::count == 1); + assert(new_called == 1); + assert(f.target()); + assert(f.target() == 0); + std::function f2(std::allocator_arg, test_allocator(), std::move(f)); + assert(A::count == 1); + assert(new_called == 1); + assert(f2.target()); + assert(f2.target() == 0); + assert(f.target() == 0); + assert(f.target() == 0); + } +#endif } diff --git a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp index eeb69560..8727f60d 100644 --- a/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp +++ b/test/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/assign_F_alloc.pass.cpp @@ -16,7 +16,45 @@ #include #include +#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 void assign(F&&, const A&); not implemented + { + std::function f; + f.assign(A(), test_allocator()); + assert(A::count == 1); + assert(f.target()); + assert(f.target() == 0); + } + assert(A::count == 0); } diff --git a/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h b/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h new file mode 100644 index 00000000..898c0900 --- /dev/null +++ b/test/utilities/function.objects/func.wrap/func.wrap.func/test_allocator.h @@ -0,0 +1,112 @@ +#ifndef TEST_ALLOCATOR_H +#define TEST_ALLOCATOR_H + +#include +#include +#include +#include +#include + +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 test_allocator + : public test_alloc_base +{ + int data_; + + template 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::type reference; + typedef typename std::add_lvalue_reference::type const_reference; + + template struct rebind {typedef test_allocator 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 test_allocator(const test_allocator& 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 other_allocator +{ + int data_; + + template friend class other_allocator; + +public: + typedef T value_type; + + other_allocator() : data_(-1) {} + explicit other_allocator(int i) : data_(i) {} + template other_allocator(const other_allocator& 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