/* Copyright (c) 2019-2020 Intel Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #ifndef __TBB_allocator_traits_H #define __TBB_allocator_traits_H #include "../tbb_stddef.h" // true/false_type #if __TBB_ALLOCATOR_TRAITS_PRESENT #include // for allocator_traits #endif #if __TBB_CPP11_RVALUE_REF_PRESENT #include // for std::move #endif // For allocator_swap helper #include __TBB_STD_SWAP_HEADER namespace tbb { namespace internal { //! Internal implementation of allocator traits, propagate_on_* use internal boolean_constant. //! In order to avoid code duplication, check what implementation of boolean constant will likely be passed. #if __TBB_ALLOCATOR_TRAITS_PRESENT typedef std::true_type traits_true_type; typedef std::false_type traits_false_type; #else typedef tbb::internal::true_type traits_true_type; typedef tbb::internal::false_type traits_false_type; #endif //! Copy assignment implementation for allocator if propagate_on_container_copy_assignment == true_type //! Noop if pocca == false_type template inline void allocator_copy_assignment(MyAlloc& my_allocator, OtherAlloc& other_allocator, traits_true_type) { my_allocator = other_allocator; } template inline void allocator_copy_assignment(MyAlloc&, OtherAlloc&, traits_false_type) { /* NO COPY */} #if __TBB_CPP11_RVALUE_REF_PRESENT //! Move assignment implementation for allocator if propagate_on_container_move_assignment == true_type. //! Noop if pocma == false_type. template inline void allocator_move_assignment(MyAlloc& my_allocator, OtherAlloc& other_allocator, traits_true_type) { my_allocator = std::move(other_allocator); } template inline void allocator_move_assignment(MyAlloc&, OtherAlloc&, traits_false_type) { /* NO MOVE */ } #endif //! Swap implementation for allocators if propagate_on_container_swap == true_type. //! Noop if pocs == false_type. template inline void allocator_swap(MyAlloc& my_allocator, OtherAlloc& other_allocator, traits_true_type) { using std::swap; swap(my_allocator, other_allocator); } template inline void allocator_swap(MyAlloc&, OtherAlloc&, traits_false_type) { /* NO SWAP */ } #if __TBB_ALLOCATOR_TRAITS_PRESENT using std::allocator_traits; #else //! Internal allocator_traits implementation, which relies on C++03 standard //! [20.1.5] allocator requirements template struct allocator_traits { // C++03 allocator doesn't have to be assignable or swappable, therefore // define these traits as false_type to do not require additional operations // that are not supposed to be in. typedef tbb::internal::false_type propagate_on_container_move_assignment; typedef tbb::internal::false_type propagate_on_container_copy_assignment; typedef tbb::internal::false_type propagate_on_container_swap; typedef Alloc allocator_type; typedef typename allocator_type::value_type value_type; typedef typename allocator_type::pointer pointer; typedef typename allocator_type::const_pointer const_pointer; typedef typename allocator_type::difference_type difference_type; typedef typename allocator_type::size_type size_type; template struct rebind_alloc { typedef typename Alloc::template rebind::other other; }; static pointer allocate(Alloc& a, size_type n) { return a.allocate(n); } static void deallocate(Alloc& a, pointer p, size_type n) { a.deallocate(p, n); } template static void construct(Alloc&, PT* p) { ::new (static_cast(p)) PT(); } template static void construct(Alloc&, PT* p, __TBB_FORWARDING_REF(T1) t1) { ::new (static_cast(p)) PT(tbb::internal::forward(t1)); } template static void construct(Alloc&, PT* p, __TBB_FORWARDING_REF(T1) t1, __TBB_FORWARDING_REF(T2) t2) { ::new (static_cast(p)) PT(tbb::internal::forward(t1), tbb::internal::forward(t2)); } template static void construct(Alloc&, PT* p, __TBB_FORWARDING_REF(T1) t1, __TBB_FORWARDING_REF(T2) t2, __TBB_FORWARDING_REF(T3) t3) { ::new (static_cast(p)) PT(tbb::internal::forward(t1), tbb::internal::forward(t2), tbb::internal::forward(t3)); } template static void destroy(Alloc&, T* p) { p->~T(); tbb::internal::suppress_unused_warning(p); } static Alloc select_on_container_copy_construction(const Alloc& a) { return a; } }; #endif // __TBB_ALLOCATOR_TRAITS_PRESENT //! C++03/C++11 compliant rebind helper, even if no std::allocator_traits available //! or rebind is not defined for allocator type template struct allocator_rebind { #if __TBB_ALLOCATOR_TRAITS_PRESENT typedef typename allocator_traits::template rebind_alloc type; #else typedef typename allocator_traits::template rebind_alloc::other type; #endif }; }} // namespace tbb::internal #endif // __TBB_allocator_traits_H