X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Fsmall_vector.h;h=67f18108b0c7b7dc37d08af0f331e57d954c6812;hp=741aaf3a896c30965ca4e085e835b8e6121377fd;hb=13cc05eaec5c19feaedc0b7fec17a6272f4b3f83;hpb=5a40209ae92c09d6c13875e5ce162cab5456c540 diff --git a/folly/small_vector.h b/folly/small_vector.h index 741aaf3a..67f18108 100644 --- a/folly/small_vector.h +++ b/folly/small_vector.h @@ -26,9 +26,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -43,14 +45,14 @@ #include #include -#include +#include #include -#include #include #include #include +#include +#include #include -#include #include #include @@ -74,25 +76,145 @@ struct NoHeap; ////////////////////////////////////////////////////////////////////// -} // small_vector_policy +} // namespace small_vector_policy ////////////////////////////////////////////////////////////////////// -template +template class small_vector; ////////////////////////////////////////////////////////////////////// namespace detail { +/* + * Move objects in memory to the right into some uninitialized + * memory, where the region overlaps. This doesn't just use + * std::move_backward because move_backward only works if all the + * memory is initialized to type T already. + */ +template +typename std::enable_if::type +moveObjectsRight(T* first, T* lastConstructed, T* realLast) { + if (lastConstructed == realLast) { + return; + } + + T* end = first - 1; // Past the end going backwards. + T* out = realLast - 1; + T* in = lastConstructed - 1; + try { + for (; in != end && out >= lastConstructed; --in, --out) { + new (out) T(std::move(*in)); + } + for (; in != end; --in, --out) { + *out = std::move(*in); + } + for (; out >= lastConstructed; --out) { + new (out) T(); + } + } catch (...) { + // We want to make sure the same stuff is uninitialized memory + // if we exit via an exception (this is to make sure we provide + // the basic exception safety guarantee for insert functions). + if (out < lastConstructed) { + out = lastConstructed - 1; + } + for (auto it = out + 1; it != realLast; ++it) { + it->~T(); + } + throw; + } +} + +// Specialization for trivially copyable types. The call to +// std::move_backward here will just turn into a memmove. (TODO: +// change to std::is_trivially_copyable when that works.) +template +typename std::enable_if::type +moveObjectsRight(T* first, T* lastConstructed, T* realLast) { + std::move_backward(first, lastConstructed, realLast); +} + +/* + * Populate a region of memory using `op' to construct elements. If + * anything throws, undo what we did. + */ +template +void populateMemForward(T* mem, std::size_t n, Function const& op) { + std::size_t idx = 0; + try { + for (size_t i = 0; i < n; ++i) { + op(&mem[idx]); + ++idx; + } + } catch (...) { + for (std::size_t i = 0; i < idx; ++i) { + mem[i].~T(); + } + throw; + } +} + +template +struct IntegralSizePolicyBase { + typedef SizeType InternalSizeType; + + IntegralSizePolicyBase() : size_(0) {} + + protected: + static constexpr std::size_t policyMaxSize() { + return SizeType(~kExternMask); + } + + std::size_t doSize() const { + return size_ & ~kExternMask; + } + + std::size_t isExtern() const { + return kExternMask & size_; + } + + void setExtern(bool b) { + if (b) { + size_ |= kExternMask; + } else { + size_ &= ~kExternMask; + } + } + + void setSize(std::size_t sz) { + assert(sz <= policyMaxSize()); + size_ = (kExternMask & size_) | SizeType(sz); + } + + void swapSizePolicy(IntegralSizePolicyBase& o) { + std::swap(size_, o.size_); + } + + protected: + static bool constexpr kShouldUseHeap = ShouldUseHeap; + + private: + static SizeType constexpr kExternMask = + kShouldUseHeap ? SizeType(1) << (sizeof(SizeType) * 8 - 1) : 0; + + SizeType size_; +}; + +template +struct IntegralSizePolicy; + +template +struct IntegralSizePolicy + : public IntegralSizePolicyBase { + public: /* * Move a range to a range of uninitialized memory. Assumes the * ranges don't overlap. */ - template - typename std::enable_if< - !FOLLY_IS_TRIVIALLY_COPYABLE(T) - >::type + template + typename std::enable_if::type moveToUninitialized(T* first, T* last, T* out) { std::size_t idx = 0; try { @@ -113,33 +235,31 @@ namespace detail { } // Specialization for trivially copyable types. - template - typename std::enable_if< - FOLLY_IS_TRIVIALLY_COPYABLE(T) - >::type + template + typename std::enable_if::type moveToUninitialized(T* first, T* last, T* out) { std::memmove(out, first, (last - first) * sizeof *first); } /* * Move a range to a range of uninitialized memory. Assumes the - * ranges don't overlap. Inserts an element at out + pos using emplaceFunc(). - * out will contain (end - begin) + 1 elements on success and none on failure. - * If emplaceFunc() throws [begin, end) is unmodified. + * ranges don't overlap. Inserts an element at out + pos using + * emplaceFunc(). out will contain (end - begin) + 1 elements on success and + * none on failure. If emplaceFunc() throws [begin, end) is unmodified. */ - template + template void moveToUninitializedEmplace( T* begin, T* end, T* out, - Size pos, + SizeType pos, EmplaceFunc&& emplaceFunc) { // Must be called first so that if it throws [begin, end) is unmodified. // We have to support the strong exception guarantee for emplace_back(). emplaceFunc(out + pos); // move old elements to the left of the new one try { - detail::moveToUninitialized(begin, begin + pos, out); + this->moveToUninitialized(begin, begin + pos, out); } catch (...) { out[pos].~T(); throw; @@ -147,236 +267,136 @@ namespace detail { // move old elements to the right of the new one try { if (begin + pos < end) { - detail::moveToUninitialized(begin + pos, end, out + pos + 1); + this->moveToUninitialized(begin + pos, end, out + pos + 1); } } catch (...) { - for (Size i = 0; i <= pos; ++i) { + for (SizeType i = 0; i <= pos; ++i) { out[i].~T(); } throw; } } +}; - /* - * Move objects in memory to the right into some uninitialized - * memory, where the region overlaps. This doesn't just use - * std::move_backward because move_backward only works if all the - * memory is initialized to type T already. - */ - template - typename std::enable_if< - !FOLLY_IS_TRIVIALLY_COPYABLE(T) - >::type - moveObjectsRight(T* first, T* lastConstructed, T* realLast) { - if (lastConstructed == realLast) { - return; - } - - T* end = first - 1; // Past the end going backwards. - T* out = realLast - 1; - T* in = lastConstructed - 1; - try { - for (; in != end && out >= lastConstructed; --in, --out) { - new (out) T(std::move(*in)); - } - for (; in != end; --in, --out) { - *out = std::move(*in); - } - for (; out >= lastConstructed; --out) { - new (out) T(); - } - } catch (...) { - // We want to make sure the same stuff is uninitialized memory - // if we exit via an exception (this is to make sure we provide - // the basic exception safety guarantee for insert functions). - if (out < lastConstructed) { - out = lastConstructed - 1; - } - for (auto it = out + 1; it != realLast; ++it) { - it->~T(); - } - throw; - } - } - - // Specialization for trivially copyable types. The call to - // std::move_backward here will just turn into a memmove. (TODO: - // change to std::is_trivially_copyable when that works.) - template - typename std::enable_if< - FOLLY_IS_TRIVIALLY_COPYABLE(T) - >::type - moveObjectsRight(T* first, T* lastConstructed, T* realLast) { - std::move_backward(first, lastConstructed, realLast); +template +struct IntegralSizePolicy + : public IntegralSizePolicyBase { + public: + template + void moveToUninitialized(T* /*first*/, T* /*last*/, T* /*out*/) { + assume_unreachable(); } - - /* - * Populate a region of memory using `op' to construct elements. If - * anything throws, undo what we did. - */ - template - void populateMemForward(T* mem, std::size_t n, Function const& op) { - std::size_t idx = 0; - try { - for (size_t i = 0; i < n; ++i) { - op(&mem[idx]); - ++idx; - } - } catch (...) { - for (std::size_t i = 0; i < idx; ++i) { - mem[i].~T(); - } - throw; - } + template + void moveToUninitializedEmplace( + T* /* begin */, + T* /* end */, + T* /* out */, + SizeType /* pos */, + EmplaceFunc&& /* emplaceFunc */) { + assume_unreachable(); } +}; - template - struct IntegralSizePolicy { - typedef SizeType InternalSizeType; - - IntegralSizePolicy() : size_(0) {} - - protected: - static constexpr std::size_t policyMaxSize() { - return SizeType(~kExternMask); - } - - std::size_t doSize() const { - return size_ & ~kExternMask; - } - - std::size_t isExtern() const { - return kExternMask & size_; - } - - void setExtern(bool b) { - if (b) { - size_ |= kExternMask; - } else { - size_ &= ~kExternMask; - } - } - - void setSize(std::size_t sz) { - assert(sz <= policyMaxSize()); - size_ = (kExternMask & size_) | SizeType(sz); - } - - void swapSizePolicy(IntegralSizePolicy& o) { - std::swap(size_, o.size_); - } - - protected: - static bool const kShouldUseHeap = ShouldUseHeap; - - private: - static SizeType const kExternMask = - kShouldUseHeap ? SizeType(1) << (sizeof(SizeType) * 8 - 1) - : 0; - - SizeType size_; - }; +/* + * If you're just trying to use this class, ignore everything about + * this next small_vector_base class thing. + * + * The purpose of this junk is to minimize sizeof(small_vector<>) + * and allow specifying the template parameters in whatever order is + * convenient for the user. There's a few extra steps here to try + * to keep the error messages at least semi-reasonable. + * + * Apologies for all the black magic. + */ +namespace mpl = boost::mpl; +template < + class Value, + std::size_t RequestedMaxInline, + class InPolicyA, + class InPolicyB, + class InPolicyC> +struct small_vector_base { + typedef mpl::vector PolicyList; /* - * If you're just trying to use this class, ignore everything about - * this next small_vector_base class thing. - * - * The purpose of this junk is to minimize sizeof(small_vector<>) - * and allow specifying the template parameters in whatever order is - * convenient for the user. There's a few extra steps here to try - * to keep the error messages at least semi-reasonable. - * - * Apologies for all the black magic. + * Determine the size type */ - namespace mpl = boost::mpl; - template - struct small_vector_base { - typedef mpl::vector PolicyList; - - /* - * Determine the size type - */ - typedef typename mpl::filter_view< + typedef typename mpl::filter_view< PolicyList, - boost::is_integral - >::type Integrals; - typedef typename mpl::eval_if< + boost::is_integral>::type Integrals; + typedef typename mpl::eval_if< mpl::empty, mpl::identity, - mpl::front - >::type SizeType; + mpl::front>::type SizeType; - static_assert(std::is_unsigned::value, - "Size type should be an unsigned integral type"); - static_assert(mpl::size::value == 0 || - mpl::size::value == 1, - "Multiple size types specified in small_vector<>"); + static_assert( + std::is_unsigned::value, + "Size type should be an unsigned integral type"); + static_assert( + mpl::size::value == 0 || mpl::size::value == 1, + "Multiple size types specified in small_vector<>"); - /* - * Determine whether we should allow spilling to the heap or not. - */ - typedef typename mpl::count< - PolicyList,small_vector_policy::NoHeap - >::type HasNoHeap; + /* + * Determine whether we should allow spilling to the heap or not. + */ + typedef typename mpl::count::type + HasNoHeap; - static_assert(HasNoHeap::value == 0 || HasNoHeap::value == 1, - "Multiple copies of small_vector_policy::NoHeap " - "supplied; this is probably a mistake"); + static_assert( + HasNoHeap::value == 0 || HasNoHeap::value == 1, + "Multiple copies of small_vector_policy::NoHeap " + "supplied; this is probably a mistake"); - /* - * Make the real policy base classes. - */ - typedef IntegralSizePolicy - ActualSizePolicy; + /* + * Make the real policy base classes. + */ + typedef IntegralSizePolicy ActualSizePolicy; - /* - * Now inherit from them all. This is done in such a convoluted - * way to make sure we get the empty base optimizaton on all these - * types to keep sizeof(small_vector<>) minimal. - */ - typedef boost::totally_ordered1< - small_vector, - ActualSizePolicy - > type; - }; + /* + * Now inherit from them all. This is done in such a convoluted + * way to make sure we get the empty base optimizaton on all these + * types to keep sizeof(small_vector<>) minimal. + */ + typedef boost::totally_ordered1< + small_vector, + ActualSizePolicy> + type; +}; - template - T* pointerFlagSet(T* p) { - return reinterpret_cast(reinterpret_cast(p) | 1); - } - template - bool pointerFlagGet(T* p) { - return reinterpret_cast(p) & 1; - } - template - T* pointerFlagClear(T* p) { - return reinterpret_cast( - reinterpret_cast(p) & ~uintptr_t(1)); - } - inline void* shiftPointer(void* p, size_t sizeBytes) { - return static_cast(p) + sizeBytes; - } +template +T* pointerFlagSet(T* p) { + return reinterpret_cast(reinterpret_cast(p) | 1); +} +template +bool pointerFlagGet(T* p) { + return reinterpret_cast(p) & 1; +} +template +T* pointerFlagClear(T* p) { + return reinterpret_cast(reinterpret_cast(p) & ~uintptr_t(1)); +} +inline void* shiftPointer(void* p, size_t sizeBytes) { + return static_cast(p) + sizeBytes; } +} // namespace detail ////////////////////////////////////////////////////////////////////// FOLLY_PACK_PUSH -template -class small_vector - : public detail::small_vector_base< - Value,RequestedMaxInline,PolicyA,PolicyB,PolicyC - >::type -{ - typedef typename detail::small_vector_base< - Value,RequestedMaxInline,PolicyA,PolicyB,PolicyC - >::type BaseType; +template < + class Value, + std::size_t RequestedMaxInline = 1, + class PolicyA = void, + class PolicyB = void, + class PolicyC = void> +class small_vector : public detail::small_vector_base< + Value, + RequestedMaxInline, + PolicyA, + PolicyB, + PolicyC>::type { + typedef typename detail:: + small_vector_base:: + type BaseType; typedef typename BaseType::InternalSizeType InternalSizeType; /* @@ -388,18 +408,22 @@ class small_vector constexpr_max(sizeof(Value*) / sizeof(Value), RequestedMaxInline)}; public: - typedef std::size_t size_type; - typedef Value value_type; - typedef value_type& reference; - typedef value_type const& const_reference; - typedef value_type* iterator; - typedef value_type const* const_iterator; - typedef std::ptrdiff_t difference_type; - - typedef std::reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef Value value_type; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef value_type* iterator; + typedef value_type* pointer; + typedef value_type const* const_iterator; + typedef std::ptrdiff_t difference_type; + + typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - explicit small_vector() = default; + small_vector() = default; + // Allocator is unused here. It is taken in for compatibility with std::vector + // interface, but it will be ignored. + small_vector(const std::allocator&) {} small_vector(small_vector const& o) { auto n = o.size(); @@ -415,14 +439,15 @@ class small_vector this->setSize(n); } - small_vector(small_vector&& o) - noexcept(std::is_nothrow_move_constructible::value) { + small_vector(small_vector&& o) noexcept( + std::is_nothrow_move_constructible::value) { if (o.isExtern()) { swap(o); } else { - std::uninitialized_copy(std::make_move_iterator(o.begin()), - std::make_move_iterator(o.end()), - begin()); + std::uninitialized_copy( + std::make_move_iterator(o.begin()), + std::make_move_iterator(o.end()), + begin()); this->setSize(o.size()); } } @@ -439,8 +464,8 @@ class small_vector doConstruct(n, [&](void* p) { new (p) value_type(t); }); } - template - explicit small_vector(Arg arg1, Arg arg2) { + template + explicit small_vector(Arg arg1, Arg arg2) { // Forward using std::is_arithmetic to get to the proper // implementation; this disambiguates between the iterators and // (size_t, value_type) meaning for this constructor. @@ -464,7 +489,9 @@ class small_vector small_vector& operator=(small_vector&& o) { // TODO: optimization: // if both are internal, use move assignment where possible - if (this == &o) return *this; + if (this == &o) { + return *this; + } clear(); swap(o); return *this; @@ -483,18 +510,38 @@ class small_vector : BaseType::policyMaxSize(); } - size_type size() const { return this->doSize(); } - bool empty() const { return !size(); } + size_type size() const { + return this->doSize(); + } + bool empty() const { + return !size(); + } - iterator begin() { return data(); } - iterator end() { return data() + size(); } - const_iterator begin() const { return data(); } - const_iterator end() const { return data() + size(); } - const_iterator cbegin() const { return begin(); } - const_iterator cend() const { return end(); } + iterator begin() { + return data(); + } + iterator end() { + return data() + size(); + } + const_iterator begin() const { + return data(); + } + const_iterator end() const { + return data() + size(); + } + const_iterator cbegin() const { + return begin(); + } + const_iterator cend() const { + return end(); + } - reverse_iterator rbegin() { return reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } + reverse_iterator rbegin() { + return reverse_iterator(end()); + } + reverse_iterator rend() { + return reverse_iterator(begin()); + } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); @@ -504,8 +551,12 @@ class small_vector return const_reverse_iterator(begin()); } - const_reverse_iterator crbegin() const { return rbegin(); } - const_reverse_iterator crend() const { return rend(); } + const_reverse_iterator crbegin() const { + return rbegin(); + } + const_reverse_iterator crend() const { + return rend(); + } /* * Usually one of the simplest functions in a Container-like class @@ -568,7 +619,7 @@ class small_vector auto& oldIntern = o.isExtern() ? *this : o; auto oldExternCapacity = oldExtern.capacity(); - auto oldExternHeap = oldExtern.u.pdata_.heap_; + auto oldExternHeap = oldExtern.u.pdata_.heap_; auto buff = oldExtern.u.buffer(); size_type i = 0; @@ -600,9 +651,8 @@ class small_vector return; } makeSize(sz); - detail::populateMemForward(begin() + size(), sz - size(), - [&] (void* p) { new (p) value_type(); } - ); + detail::populateMemForward( + begin() + size(), sz - size(), [&](void* p) { new (p) value_type(); }); this->setSize(sz); } @@ -612,9 +662,8 @@ class small_vector return; } makeSize(sz); - detail::populateMemForward(begin() + size(), sz - size(), - [&] (void* p) { new (p) value_type(v); } - ); + detail::populateMemForward( + begin() + size(), sz - size(), [&](void* p) { new (p) value_type(v); }); this->setSize(sz); } @@ -626,7 +675,7 @@ class small_vector return this->isExtern() ? u.heap() : u.buffer(); } - template + template iterator emplace(const_iterator p, Args&&... args) { if (p == cend()) { emplace_back(std::forward(args)...); @@ -720,14 +769,12 @@ class small_vector offset); this->setSize(this->size() + 1); } else { - detail::moveObjectsRight(data() + offset, - data() + size(), - data() + size() + 1); + detail::moveObjectsRight( + data() + offset, data() + size(), data() + size() + 1); this->setSize(size() + 1); data()[offset] = std::move(t); } return begin() + offset; - } iterator insert(const_iterator p, value_type const& t) { @@ -739,15 +786,14 @@ class small_vector iterator insert(const_iterator pos, size_type n, value_type const& val) { auto offset = pos - begin(); makeSize(size() + n); - detail::moveObjectsRight(data() + offset, - data() + size(), - data() + size() + n); + detail::moveObjectsRight( + data() + offset, data() + size(), data() + size() + n); this->setSize(size() + n); std::generate_n(begin() + offset, n, [&] { return val; }); return begin() + offset; } - template + template iterator insert(const_iterator p, Arg arg1, Arg arg2) { // Forward using std::is_arithmetic to get to the proper // implementation; this disambiguates between the iterators and @@ -767,7 +813,9 @@ class small_vector } iterator erase(const_iterator q1, const_iterator q2) { - if (q1 == q2) return unconst(q1); + if (q1 == q2) { + return unconst(q1); + } std::move(unconst(q2), end(), unconst(q1)); for (auto it = (end() - std::distance(q1, q2)); it != end(); ++it) { it->~value_type(); @@ -780,7 +828,7 @@ class small_vector erase(begin(), end()); } - template + template void assign(Arg first, Arg last) { clear(); insert(end(), first, last); @@ -795,10 +843,22 @@ class small_vector insert(end(), n, t); } - reference front() { assert(!empty()); return *begin(); } - reference back() { assert(!empty()); return *(end() - 1); } - const_reference front() const { assert(!empty()); return *begin(); } - const_reference back() const { assert(!empty()); return *(end() - 1); } + reference front() { + assert(!empty()); + return *begin(); + } + reference back() { + assert(!empty()); + return *(end() - 1); + } + const_reference front() const { + assert(!empty()); + return *begin(); + } + const_reference back() const { + assert(!empty()); + return *(end() - 1); + } reference operator[](size_type i) { assert(i < size()); @@ -824,18 +884,17 @@ class small_vector return (*this)[i]; } -private: - + private: static iterator unconst(const_iterator it) { return const_cast(it); } // The std::false_type argument is part of disambiguating the // iterator insert functions from integral types (see insert().) - template + template iterator insertImpl(iterator pos, It first, It last, std::false_type) { typedef typename std::iterator_traits::iterator_category categ; - if (std::is_same::value) { + if (std::is_same::value) { auto offset = pos - begin(); while (first != last) { pos = insert(pos, *first++); @@ -847,16 +906,15 @@ private: auto distance = std::distance(first, last); auto offset = pos - begin(); makeSize(size() + distance); - detail::moveObjectsRight(data() + offset, - data() + size(), - data() + size() + distance); + detail::moveObjectsRight( + data() + offset, data() + size(), data() + size() + distance); this->setSize(size() + distance); std::copy_n(first, distance, begin() + offset); return begin() + offset; } - iterator insertImpl(iterator pos, size_type n, const value_type& val, - std::true_type) { + iterator + insertImpl(iterator pos, size_type n, const value_type& val, std::true_type) { // The true_type means this should call the size_t,value_type // overload. (See insert().) return insert(pos, n, val); @@ -865,10 +923,10 @@ private: // The std::false_type argument came from std::is_arithmetic as part // of disambiguating an overload (see the comment in the // constructor). - template + template void constructImpl(It first, It last, std::false_type) { typedef typename std::iterator_traits::iterator_category categ; - if (std::is_same::value) { + if (std::is_same::value) { // With iterators that only allow a single pass, we can't really // do anything sane here. while (first != last) { @@ -881,9 +939,8 @@ private: makeSize(distance); this->setSize(distance); try { - detail::populateMemForward(data(), distance, - [&] (void* p) { new (p) value_type(*first++); } - ); + detail::populateMemForward( + data(), distance, [&](void* p) { new (p) value_type(*first++); }); } catch (...) { if (this->isExtern()) { u.freeHeap(); @@ -953,6 +1010,15 @@ private: assert(!insert); return; } + + assert(this->kShouldUseHeap); + // This branch isn't needed for correctness, but allows the optimizer to + // skip generating code for the rest of this function in NoHeap + // small_vectors. + if (!this->kShouldUseHeap) { + return; + } + newSize = std::max(newSize, computeNewSize()); auto needBytes = newSize * sizeof(value_type); @@ -960,7 +1026,7 @@ private: // allocation is grown to over some threshold, we should store // a capacity at the front of the heap allocation. bool heapifyCapacity = - !kHasInlineCapacity && needBytes > kHeapifyCapacityThreshold; + !kHasInlineCapacity && needBytes > kHeapifyCapacityThreshold; if (heapifyCapacity) { needBytes += kHeapifyCapacitySize; } @@ -971,18 +1037,17 @@ private: assert(!detail::pointerFlagGet(newh)); value_type* newp = static_cast( - heapifyCapacity ? - detail::shiftPointer(newh, kHeapifyCapacitySize) : - newh); + heapifyCapacity ? detail::shiftPointer(newh, kHeapifyCapacitySize) + : newh); try { if (insert) { // move and insert the new element - detail::moveToUninitializedEmplace( + this->moveToUninitializedEmplace( begin(), end(), newp, pos, std::forward(emplaceFunc)); } else { // move without inserting new element - detail::moveToUninitialized(begin(), end(), newp); + this->moveToUninitialized(begin(), end(), newp); } } catch (...) { free(newh); @@ -1018,7 +1083,7 @@ private: } } -private: + private: struct HeapPtrWithCapacity { void* heap_; InternalSizeType capacity_; @@ -1049,38 +1114,35 @@ private: typedef unsigned char InlineStorageDataType[sizeof(value_type) * MaxInline]; #else typedef typename std::aligned_storage< - sizeof(value_type) * MaxInline, - alignof(value_type) - >::type InlineStorageDataType; + sizeof(value_type) * MaxInline, + alignof(value_type)>::type InlineStorageDataType; #endif typedef typename std::conditional< - sizeof(value_type) * MaxInline != 0, - InlineStorageDataType, - void* - >::type InlineStorageType; + sizeof(value_type) * MaxInline != 0, + InlineStorageDataType, + void*>::type InlineStorageType; - static bool const kHasInlineCapacity = - sizeof(HeapPtrWithCapacity) < sizeof(InlineStorageType); + static bool constexpr kHasInlineCapacity = + sizeof(HeapPtrWithCapacity) < sizeof(InlineStorageType); // This value should we multiple of word size. - static size_t const kHeapifyCapacitySize = sizeof( - typename std::aligned_storage< - sizeof(InternalSizeType), - alignof(value_type) - >::type); + static size_t constexpr kHeapifyCapacitySize = sizeof( + typename std:: + aligned_storage::type); + // Threshold to control capacity heapifying. - static size_t const kHeapifyCapacityThreshold = - 100 * kHeapifyCapacitySize; + static size_t constexpr kHeapifyCapacityThreshold = + 100 * kHeapifyCapacitySize; - typedef typename std::conditional< - kHasInlineCapacity, - HeapPtrWithCapacity, - HeapPtr - >::type PointerType; + typedef typename std:: + conditional::type + PointerType; union Data { - explicit Data() { pdata_.heap_ = 0; } + explicit Data() { + pdata_.heap_ = nullptr; + } PointerType pdata_; InlineStorageType storage_; @@ -1126,9 +1188,10 @@ FOLLY_PACK_POP // Basic guarantee only, or provides the nothrow guarantee iff T has a // nothrow move or copy constructor. -template -void swap(small_vector& a, - small_vector& b) { +template +void swap( + small_vector& a, + small_vector& b) { a.swap(b); } @@ -1139,11 +1202,10 @@ namespace detail { // Format support. template struct IndexableTraits> - : public IndexableTraitsSeq> { -}; + : public IndexableTraitsSeq> {}; -} // namespace detail +} // namespace detail -} // namespace folly +} // namespace folly FOLLY_POP_WARNING