diff --git a/include/__functional_03 b/include/__functional_03 index f048ea324..993548342 100644 --- a/include/__functional_03 +++ b/include/__functional_03 @@ -333,7 +333,8 @@ template __base<_Rp()>* __func<_Fp, _Alloc, _Rp()>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -359,7 +360,8 @@ template void __func<_Fp, _Alloc, _Rp()>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -417,7 +419,8 @@ template __base<_Rp(_A0)>* __func<_Fp, _Alloc, _Rp(_A0)>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -443,7 +446,8 @@ template void __func<_Fp, _Alloc, _Rp(_A0)>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -501,7 +505,8 @@ template __base<_Rp(_A0, _A1)>* __func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -527,7 +532,8 @@ template void __func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -585,7 +591,8 @@ template __base<_Rp(_A0, _A1, _A2)>* __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -611,7 +618,8 @@ template void __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -794,7 +802,7 @@ function<_Rp()>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { @@ -1091,7 +1099,7 @@ function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { @@ -1388,7 +1396,7 @@ function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { @@ -1685,7 +1693,7 @@ function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _Fp if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp index 741a3b9a9..352ecfc60 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp @@ -17,84 +17,90 @@ #include #include "min_allocator.h" +#include "test_allocator.h" +#include "count_new.hpp" +#include "../function_types.h" -class A +class DummyClass {}; + +template +void test_FunctionObject(AllocType& alloc) { - int data_[10]; -public: - static int count; - - A() + assert(globalMemCounter.checkOutstandingNewEq(0)); { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = i; + FunctionObject target; + assert(FunctionObject::count == 1); + assert(globalMemCounter.checkOutstandingNewEq(0)); + std::function f2(std::allocator_arg, alloc, target); + assert(FunctionObject::count == 2); + assert(globalMemCounter.checkOutstandingNewEq(1)); + assert(f2.template target()); + assert(f2.template target() == 0); + assert(f2.template target() == 0); } + assert(FunctionObject::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); +} - A(const A&) {++count;} - ~A() {--count;} - - int operator()(int i) const +template +void test_FreeFunction(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; + FuncType* target = &FreeFunction; + assert(globalMemCounter.checkOutstandingNewEq(0)); + std::function f2(std::allocator_arg, alloc, target); + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f2.template target()); + assert(*f2.template target() == target); + assert(f2.template target() == 0); + assert(f2.template target() == 0); } + assert(globalMemCounter.checkOutstandingNewEq(0)); +} - int foo(int) const {return 1;} -}; +template +void test_MemFunClass(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + TargetType target = &MemFunClass::foo; + assert(globalMemCounter.checkOutstandingNewEq(0)); + std::function f2(std::allocator_arg, alloc, target); + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f2.template target()); + assert(*f2.template target() == target); + assert(f2.template target() == 0); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); +} -int A::count = 0; +template +void test_for_alloc(Alloc& alloc) { + test_FunctionObject(alloc); + test_FunctionObject(alloc); + test_FunctionObject(alloc); + test_FunctionObject(alloc); -int g(int) {return 0;} + test_FreeFunction(alloc); + test_FreeFunction(alloc); + test_FreeFunction(alloc); + test_FreeFunction(alloc); -class Foo { -public: - void bar(int k) { } -}; + test_MemFunClass(alloc); + test_MemFunClass(alloc); + test_MemFunClass(alloc); +} int main() { { - std::function f(std::allocator_arg, bare_allocator(), A()); - assert(A::count == 1); - assert(f.target()); - assert(f.target() == 0); - } - assert(A::count == 0); - { - std::function f(std::allocator_arg, bare_allocator(), g); - assert(f.target()); - assert(f.target() == 0); + bare_allocator bare_alloc; + test_for_alloc(bare_alloc); } { - std::function f(std::allocator_arg, bare_allocator(), - (int (*)(int))0); - assert(!f); - assert(f.target() == 0); - assert(f.target() == 0); - } - { - std::function f(std::allocator_arg, - bare_allocator(), - &A::foo); - assert(f); - assert(f.target() != 0); - } -#if __cplusplus >= 201103L - { - Foo f; - std::function fun = std::bind(&Foo::bar, &f, std::placeholders::_1); - fun(10); - } -#endif - { - std::function fun(std::allocator_arg, - bare_allocator(), - &g); - assert(fun); - assert(fun.target() != 0); - fun(10); + non_default_test_allocator non_default_alloc(42); + test_for_alloc(non_default_alloc); } } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp index e89636a69..371eb98de 100644 --- a/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp @@ -20,81 +20,105 @@ #include "min_allocator.h" #include "test_allocator.h" #include "count_new.hpp" +#include "../function_types.h" -class A +class DummyClass {}; + +template +void test_FunctionObject(AllocType& alloc) { - int data_[10]; -public: - static int count; - - A() + assert(globalMemCounter.checkOutstandingNewEq(0)); { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = i; + // Construct function from FunctionObject. + std::function f = FunctionObject(); + assert(FunctionObject::count == 1); + assert(globalMemCounter.checkOutstandingNewEq(1)); + assert(f.template target()); + assert(f.template target() == 0); + assert(f.template target() == 0); + // Copy function with allocator + std::function f2(std::allocator_arg, alloc, f); + assert(FunctionObject::count == 2); + assert(globalMemCounter.checkOutstandingNewEq(2)); + assert(f2.template target()); + assert(f2.template target() == 0); + assert(f2.template target() == 0); } + assert(FunctionObject::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); +} - A(const A&) {++count;} - - ~A() {--count;} - - int operator()(int i) const +template +void test_FreeFunction(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; + // Construct function from function pointer. + FuncType* target = &FreeFunction; + std::function f = target; + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f.template target()); + assert(*f.template target() == target); + assert(f.template target() == 0); + // Copy function with allocator + std::function f2(std::allocator_arg, alloc, f); + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f2.template target()); + assert(*f2.template target() == target); + assert(f2.template target() == 0); } -}; + assert(globalMemCounter.checkOutstandingNewEq(0)); +} -int A::count = 0; +template +void test_MemFunClass(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + // Construct function from function pointer. + TargetType target = &MemFunClass::foo; + std::function f = target; + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f.template target()); + assert(*f.template target() == target); + assert(f.template target() == 0); + // Copy function with allocator + std::function f2(std::allocator_arg, alloc, f); + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f2.template target()); + assert(*f2.template target() == target); + assert(f2.template target() == 0); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); +} -int g(int) {return 0;} +template +void test_for_alloc(Alloc& alloc) +{ + // Large FunctionObject -- Allocation should occur + test_FunctionObject(alloc); + test_FunctionObject(alloc); + test_FunctionObject(alloc); + test_FunctionObject(alloc); + // Free function -- No allocation should occur + test_FreeFunction(alloc); + test_FreeFunction(alloc); + test_FreeFunction(alloc); + test_FreeFunction(alloc); + // Member function -- No allocation should occur. + test_MemFunClass(alloc); + test_MemFunClass(alloc); + test_MemFunClass(alloc); +} int main() { - assert(globalMemCounter.checkOutstandingNewEq(0)); - { - std::function f = A(); - assert(A::count == 1); - assert(globalMemCounter.checkOutstandingNewEq(1)); - assert(f.target()); - assert(f.target() == 0); - std::function f2(std::allocator_arg, bare_allocator(), f); - assert(A::count == 2); - assert(globalMemCounter.checkOutstandingNewEq(2)); - assert(f2.target()); - assert(f2.target() == 0); - } - assert(A::count == 0); - assert(globalMemCounter.checkOutstandingNewEq(0)); - { - std::function f = g; - assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target()); - assert(f.target() == 0); - std::function f2(std::allocator_arg, bare_allocator(), f); - assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target()); - assert(f2.target() == 0); - } - assert(globalMemCounter.checkOutstandingNewEq(0)); - { - assert(globalMemCounter.checkOutstandingNewEq(0)); - non_default_test_allocator > al(1); - std::function f2(std::allocator_arg, al, g); - assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target()); - assert(f2.target() == 0); - } - assert(globalMemCounter.checkOutstandingNewEq(0)); - { - std::function f; - assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target() == 0); - assert(f.target() == 0); - std::function f2(std::allocator_arg, bare_allocator(), f); - assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target() == 0); - assert(f2.target() == 0); - } + { + bare_allocator alloc; + test_for_alloc(alloc); + } + { + non_default_test_allocator alloc(42); + test_for_alloc(alloc); + } } diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h b/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h new file mode 100644 index 000000000..55eb80f43 --- /dev/null +++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h @@ -0,0 +1,57 @@ +#ifndef FUNCTION_TYPES_H +#define FUNCTION_TYPES_H + + +class FunctionObject +{ + int data_[10]; // dummy variable to prevent small object optimization in + // std::function +public: + static int count; + + FunctionObject() { + ++count; + for (int i = 0; i < 10; ++i) data_[i] = i; + } + + FunctionObject(const FunctionObject&) {++count;} + ~FunctionObject() {--count; ((void)data_); } + + int operator()() const { return 42; } + int operator()(int i) const { return i; } + int operator()(int i, int) const { return i; } + int operator()(int i, int, int) const { return i; } +}; + +int FunctionObject::count = 0; + +class MemFunClass +{ + int data_[10]; // dummy variable to prevent small object optimization in + // std::function +public: + static int count; + + MemFunClass() { + ++count; + for (int i = 0; i < 10; ++i) data_[i] = 0; + } + + MemFunClass(const MemFunClass&) {++count; ((void)data_); } + + ~MemFunClass() {--count;} + + int foo() const { return 42; } + int foo(int i) const { return i; } + int foo(int i, int) const { return i; } + int foo(int i, int, int) const { return i; } +}; + +int MemFunClass::count = 0; + +int FreeFunction() { return 42; } +int FreeFunction(int i) {return i;} +int FreeFunction(int i, int) { return i; } +int FreeFunction(int i, int, int) { return i; } + +#endif // FUNCTION_TYPES_H diff --git a/test/support/test_allocator.h b/test/support/test_allocator.h index 03bd39056..47ef1d556 100644 --- a/test/support/test_allocator.h +++ b/test/support/test_allocator.h @@ -74,10 +74,10 @@ public: } ++time_to_throw; ++alloc_count; - return (pointer)std::malloc(n * sizeof(T)); + return (pointer)::operator new(n * sizeof(T)); } void deallocate(pointer p, size_type n) - {assert(data_ >= 0); --alloc_count; std::free(p);} + {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p);} size_type max_size() const throw() {return UINT_MAX / sizeof(T);} void construct(pointer p, const T& val) @@ -134,10 +134,10 @@ public: } ++time_to_throw; ++alloc_count; - return (pointer)std::malloc(n * sizeof(T)); + return (pointer)::operator new (n * sizeof(T)); } void deallocate(pointer p, size_type n) - {assert(data_ >= 0); --alloc_count; std::free(p);} + {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p); } size_type max_size() const throw() {return UINT_MAX / sizeof(T);} void construct(pointer p, const T& val) @@ -200,9 +200,9 @@ public: template other_allocator(const other_allocator& a) : data_(a.data_) {} T* allocate(std::size_t n) - {return (T*)std::malloc(n * sizeof(T));} + {return (T*)::operator new(n * sizeof(T));} void deallocate(T* p, std::size_t n) - {std::free(p);} + {::operator delete((void*)p);} other_allocator select_on_container_copy_construction() const {return other_allocator(-2);}