// bslalg_dequeiterator.h -*-C++-*- #ifndef INCLUDED_BSLALG_DEQUEITERATOR #define INCLUDED_BSLALG_DEQUEITERATOR #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a primitive iterator over deque data structures. // //@CLASSES: // bslalg::DequeIterator: primitive iterator over a deque data structure // //@SEE_ALSO: bslalg_dequeimputil, bslalg_dequeprimitives // //@DESCRIPTION: This component provides an in-core value semantic class, // 'bslalg::DequeIterator', that is a primitive iterator type for enumerating // elements in a deque (implemented in the form of a dynamic array) knowing // only its value type and a nominal block size. Conceptually, a deque is an // array of block pointers, each block capable of containing a fixed number of // objects. An element in the deque is identified by an iterator that consists // of two pointers: //: o a pointer to the block pointer array, and //: o a pointer to a value within the block referred to by the first pointer. // // Dereferencing the iterator dereferences the second pointer. Incrementing or // decrementing the iterator consists of incrementing the value pointer, unless // the iterator crosses a block boundary in which case it must increment or // decrement its pointer to the block pointer. Computing the distance between // two iterators involves figuring out how many block are in between and how // the offsets-in-block differ. // // Note that an iterator is valid as long as the element it points to still // belongs to the deque *and* there is no reallocation of the block pointer // array. Inserting elements at either end of the deque usually maintains // iterator validity, but inserting enough elements at the end of the queue // might force the creating of sufficiently many blocks to trigger a // reallocation of the block pointer array and invalidate all iterators into // the deque; how many depends on the distances between the front and back of // the deque and the first/last iterator in the block pointer array (19 in the // picture below). // // The picture is as follows: //.. // v--- Iterator to 'I': ptr to this BlockPtr // +-----+-----+-----+-----+-----+-----+-----+-----+ // | * | * | * | * | * | * | * | * | BlockPtr array // +-----+-----+--|--+--|--+--|--+--|--+-----+-----+ // | | | | Block // | | | | +---+---+---+---+---+---+---+---+ // | | | `--| V | W | X | Y | Z | | | | // | | | +---+---+---+---+---+---+---+---+ // | | | Block // | | | +---+---+---+---+---+---+---+---+ // | | `--| N | O | P | Q | R | S | T | U | // | | +---+---+---+---+---+---+---+---+ // | | v---- Iterator to 'I': ptr to value // | | +---+---+---+---+---+---+---+---+ // | `--| F | G | H | I | J | K | L | M | // | +---+---+---+---+---+---+---+---+ // | Block // | +---+---+---+---+---+---+---+---+ // `--| | | | A | B | C | D | E | // +---+---+---+---+---+---+---+---+ //.. // Depicted above is a deque consisting of eight block pointers, only four // actually used to point to blocks of eight elements. In the first block, the // first three elements are uninitialized, and the twenty six elements follow // in sequence across the different blocks. An iterator to the 'I' element // consists of a pointer to the fourth block pointer and a pointer to the sixth // element of that block. The value of the corresponding deque would be // '[ A, B, C, ... X, Y, Z ]', its logical length 26, and its capacity would be // 19 (the minimum number of prepend/append to force a reallocation of the // block pointer array). // // This component does not provide the full interface of a C++ standard library // iterator as we do not want a dependency on 'iterator_traits' in a package // below 'bslstl'. 'bslalg::DequeIterator' provides the minimal necessary set // of features to implement such an iterator for a standard conforming 'deque' // implementation in a higher level component. // ///Usage ///----- // This component is for use by the 'bslstl' package. Other clients should use // the STL deque (in header '<deque>'). #include <bslscm_version.h> #include <bslalg_dequeimputil.h> #include <bslmf_istriviallycopyable.h> #include <bsls_assert.h> #include <cstddef> // std::size_t, std::ptrdiff_t namespace BloombergLP { namespace bslalg { template <class VALUE_TYPE, int BLOCK_LENGTH> class DequeIterator; template <class VALUE_TYPE> class DequeIterator<VALUE_TYPE, 1>; // =================== // class DequeIterator // =================== template <class VALUE_TYPE, int BLOCK_LENGTH> class DequeIterator { // Implementation of a deque iterator, parameterized by the 'VALUE_TYPE', // for a deque with the parameterized 'BLOCK_LENGTH', and suitable for use // by the 'bslstl::RandomAccessIterator' adapter. Note that 'BLOCK_LENGTH' // is the number of items of 'VALUE_TYPE' within a block, not the size of a // block in bytes. // PRIVATE TYPES typedef bslalg::DequeImpUtil<VALUE_TYPE, BLOCK_LENGTH> DequeImpUtil; typedef typename DequeImpUtil::BlockPtr BlockPtr; typedef DequeIterator<VALUE_TYPE, BLOCK_LENGTH> IteratorType; // DATA BlockPtr *d_blockPtr_p; VALUE_TYPE *d_value_p; // FRIENDS friend bool operator==(const DequeIterator& lhs, const DequeIterator& rhs) // Return 'true' if the specified 'lhs' iterator points to the same // element in the same block as the specified 'rhs' iterator, and // 'false' otherwise. The behavior is undefined unless 'lhs' and 'rhs' // are iterators over the same deque. Note that this friend is a // regular functon, not a function template, so there is no way to // declare it outside the class in order to provide the definition. { return lhs.d_value_p == rhs.d_value_p; } friend bool operator!=(const DequeIterator& lhs, const DequeIterator& rhs) // Return 'true' if the specified 'lhs' iterator points to a different // element in the same block as the specified 'rhs' iterator, or points // to an element in a different block to the 'rhs' iterator, and // 'false' otherwise. The behavior is undefined unless 'lhs' and 'rhs' // are iterators over the same deque. Note that this friend is a // regular functon, not a function template, so there is no way to // declare it outside the class in order to provide the definition. { return lhs.d_value_p != rhs.d_value_p; } friend bool operator<(const DequeIterator& lhs, const DequeIterator& rhs) // Return 'true' if the specified 'lhs' iterator points to an element // in a previous block or in a previous position in the same block as // the specified 'rhs' iterator, and 'false' otherwise. The behavior // is undefined unless 'lhs' and 'rhs' are iterators over the same // deque. Note that this friend is a regular functon, not a function // template, so there is no way to declare it outside the class in // order to provide the definition. { if (lhs.d_blockPtr_p == rhs.d_blockPtr_p) { return lhs.d_value_p < rhs.d_value_p; // RETURN } else { return lhs.d_blockPtr_p < rhs.d_blockPtr_p; // RETURN } } public: // CREATORS DequeIterator(); // Create a singular iterator (i.e., having internal null pointers). explicit DequeIterator(BlockPtr *blockPtrPtr); // Create an iterator pointing to the first element in the block // pointed to by the specified 'blockPtrPtr'. DequeIterator(BlockPtr *blockPtrPtr, VALUE_TYPE *valuePtr); // Create an iterator pointing to the element at the specified // 'valuePtr' address in the block pointed to by the specified // 'blockPtrPtr'. The behavior is undefined unless 'valuePtr' points // into the block '*blockPtrPtr'. // MANIPULATORS void operator++(); // Increment this iterator to point to the next element in the // corresponding deque (i.e., the element following the current one in // the same block or, if the current element is the last one in the // block, the first element in the next block). void operator--(); // Decrement this iterator to point to the previous element in the // corresponding deque (i.e., the element preceding the current one in // the same block or, if the current element is the first one in the // block, the last element in the previous block). void operator+=(std::ptrdiff_t offset); // Advance this iterator by the specified 'offset'. void operator-=(std::ptrdiff_t offset); // Move this iterator backward by the specified 'offset'. void nextBlock(); // Set this iterator to point to the first element of the next block. void previousBlock(); // Set this iterator to point to the first (not the last) element of // the previous block. void setBlock(BlockPtr *blockPtrPtr); // Set this iterator to point to the first element of the block pointed // to by the specified 'blockPtrPtr'. void valuePtrDecrement(); // Decrement this iterator to point to the next element in the block of // the corresponding deque. The behavior is undefined unless this // iterator is pointed to a valid position of the deque. Note that // this method is used only for optimization purposes in // 'bslstl_Deque', and clients of this package should not use this // directly. void valuePtrIncrement(); // Increment this iterator to point to the next element in the block of // the corresponding deque. The behavior is undefined unless this // iterator is pointed to a valid position of the deque. Note that // this method is used only for optimization purposes in // 'bslstl_Deque', and clients of this package should not use this // directly. // ACCESSORS VALUE_TYPE& operator*() const; // Return a reference to the parameterized 'VALUE_TYPE' object pointed // to by this iterator. Note that this value is modifiable if // 'VALUE_TYPE' is modifiable, and non-modifiable if it is not. DequeIterator operator+(std::ptrdiff_t offset) const; // Return an iterator pointing the element at the specified 'offset' // after this iterator. DequeIterator operator-(std::ptrdiff_t offset) const; // Return an iterator pointing the element at the specified 'offset' // before this iterator. std::ptrdiff_t operator-(const DequeIterator& rhs) const; // Return the distance between this iterator and the specified 'rhs' // iterator. VALUE_TYPE *blockBegin() const; // Return the address of the first element in the block pointed to by // this iterator. VALUE_TYPE *blockEnd() const; // Return the address of (one-past) the last element in the block // pointed to by this iterator. BlockPtr *blockPtr() const; // Return the address of the block pointer pointed to by this iterator. std::size_t offsetInBlock() const; // Return the offset of the element pointed to by this iterator, from // the beginning of the block containing it. std::size_t remainingInBlock() const; // Return the number of elements in the block pointed to by this // iterator, until the end of this block, starting at (and including) // the element pointed to by this iterator. VALUE_TYPE *valuePtr() const; // Return the address of the parameterized 'VALUE_TYPE' object pointed // to by this iterator. }; // PARTIAL SPECIALIZATION template <class VALUE_TYPE> class DequeIterator<VALUE_TYPE, 1> { // This partial specialization of 'DequeIterator' for the case when there // is a single element per block uses simpler storage and a simpler // implementation. The contract for all functions is the same, and so not // repeated. // PRIVATE TYPES typedef bslalg::DequeImpUtil<VALUE_TYPE, 1> DequeImpUtil; typedef typename DequeImpUtil::BlockPtr BlockPtr; typedef DequeIterator<VALUE_TYPE, 1> IteratorType; // DATA BlockPtr *d_blockPtr_p; // pointer to BlockPtr within BlockPtr array VALUE_TYPE *d_value_p; // pointer to element referenced by iterator // FRIENDS friend bool operator==(const DequeIterator& lhs, const DequeIterator& rhs) { return lhs.d_blockPtr_p == rhs.d_blockPtr_p; } friend bool operator!=(const DequeIterator& lhs, const DequeIterator& rhs) { return lhs.d_blockPtr_p != rhs.d_blockPtr_p; } friend bool operator<(const DequeIterator& lhs, const DequeIterator& rhs) { return lhs.d_blockPtr_p < rhs.d_blockPtr_p; } public: // CREATORS DequeIterator(); DequeIterator(BlockPtr *blockPtrPtr); DequeIterator(BlockPtr *blockPtrPtr, VALUE_TYPE *valuePtr); // MANIPULATORS void operator++(); void operator--(); void operator+=(std::ptrdiff_t offset); void operator-=(std::ptrdiff_t offset); void nextBlock(); void previousBlock(); void setBlock(BlockPtr *blockPtrPtr); void valuePtrDecrement(); void valuePtrIncrement(); // ACCESSORS VALUE_TYPE& operator*() const; DequeIterator operator+(std::ptrdiff_t offset) const; DequeIterator operator-(std::ptrdiff_t offset) const; std::ptrdiff_t operator-(const DequeIterator& rhs) const; VALUE_TYPE *blockBegin() const; VALUE_TYPE *blockEnd() const; BlockPtr *blockPtr() const; std::size_t offsetInBlock() const; std::size_t remainingInBlock() const; VALUE_TYPE *valuePtr() const; }; // ============================================================================ // INLINE FUNCTION DEFINITIONS // ============================================================================ // ------------------- // class DequeIterator // ------------------- // CREATORS template <class VALUE_TYPE, int BLOCK_LENGTH> inline DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::DequeIterator() : d_blockPtr_p(0) , d_value_p(0) { } template <class VALUE_TYPE, int BLOCK_LENGTH> inline DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::DequeIterator(BlockPtr *blockPtrPtr) : d_blockPtr_p(blockPtrPtr) , d_value_p(reinterpret_cast<VALUE_TYPE*>(*blockPtrPtr)) { } template <class VALUE_TYPE, int BLOCK_LENGTH> inline DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::DequeIterator(BlockPtr *blockPtrPtr, VALUE_TYPE *valuePtr) : d_blockPtr_p(blockPtrPtr) , d_value_p(valuePtr) { // Trivially true, or undefined behavior, without the cast. BSLS_ASSERT_SAFE( reinterpret_cast<bsls::Types::UintPtr>((void*)blockPtrPtr[0]->d_data) <= reinterpret_cast<bsls::Types::UintPtr>((void*)valuePtr)); BSLS_ASSERT_SAFE(valuePtr - blockPtrPtr[0]->d_data < BLOCK_LENGTH); } // MANIPULATORS template <class VALUE_TYPE, int BLOCK_LENGTH> void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator++() { if (1 == this->remainingInBlock()) { ++d_blockPtr_p; d_value_p = this->blockBegin(); } else { ++d_value_p; } } template <class VALUE_TYPE, int BLOCK_LENGTH> void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator--() { if (0 == this->offsetInBlock()) { --d_blockPtr_p; d_value_p = this->blockEnd(); } --d_value_p; } template <class VALUE_TYPE, int BLOCK_LENGTH> void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator+=(std::ptrdiff_t offset) { offset += offsetInBlock(); if (offset >= 0) { d_blockPtr_p += offset / BLOCK_LENGTH; d_value_p = blockBegin() + (offset % BLOCK_LENGTH); } else { d_blockPtr_p -= (-offset - 1) / BLOCK_LENGTH + 1; d_value_p = blockEnd() - ((-offset - 1) % BLOCK_LENGTH + 1); } } template <class VALUE_TYPE, int BLOCK_LENGTH> inline void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator-=(std::ptrdiff_t offset) { this->operator+=(-offset); } template <class VALUE_TYPE, int BLOCK_LENGTH> inline void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::nextBlock() { ++d_blockPtr_p; d_value_p = this->blockBegin(); } template <class VALUE_TYPE, int BLOCK_LENGTH> inline void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::previousBlock() { --d_blockPtr_p; d_value_p = this->blockBegin(); } template <class VALUE_TYPE, int BLOCK_LENGTH> inline void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::setBlock(BlockPtr *blockPtrPtr) { d_blockPtr_p = blockPtrPtr; d_value_p = this->blockBegin(); } template <class VALUE_TYPE, int BLOCK_LENGTH> inline void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::valuePtrDecrement() { BSLS_ASSERT_SAFE(d_blockPtr_p[0]->d_data <= d_value_p); BSLS_ASSERT_SAFE(d_value_p < d_blockPtr_p[0]->d_data + BLOCK_LENGTH); --d_value_p; } template <class VALUE_TYPE, int BLOCK_LENGTH> inline void DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::valuePtrIncrement() { BSLS_ASSERT_SAFE(d_blockPtr_p[0]->d_data <= d_value_p); BSLS_ASSERT_SAFE(d_value_p < d_blockPtr_p[0]->d_data + BLOCK_LENGTH); ++d_value_p; } // ACCESSORS template <class VALUE_TYPE, int BLOCK_LENGTH> inline VALUE_TYPE& DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator*() const { return *d_value_p; } template <class VALUE_TYPE, int BLOCK_LENGTH> inline DequeIterator<VALUE_TYPE, BLOCK_LENGTH> DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator+(std::ptrdiff_t offset) const { DequeIterator ret(*this); ret += offset; return ret; } template <class VALUE_TYPE, int BLOCK_LENGTH> inline DequeIterator<VALUE_TYPE, BLOCK_LENGTH> DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator-(std::ptrdiff_t offset) const { DequeIterator ret(*this); ret += -offset; return ret; } template <class VALUE_TYPE, int BLOCK_LENGTH> std::ptrdiff_t DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::operator-( const DequeIterator<VALUE_TYPE, BLOCK_LENGTH>& rhs) const { if (d_blockPtr_p == rhs.d_blockPtr_p) { return d_value_p - rhs.d_value_p; // RETURN } else { const int numFullBlocks = static_cast<int>( this->d_blockPtr_p - rhs.d_blockPtr_p - 1); return (numFullBlocks * BLOCK_LENGTH + rhs.remainingInBlock() + this->offsetInBlock()); // RETURN } } template <class VALUE_TYPE, int BLOCK_LENGTH> inline VALUE_TYPE * DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::blockBegin() const { return reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE, int BLOCK_LENGTH> inline VALUE_TYPE * DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::blockEnd() const { return reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p) + BLOCK_LENGTH; } template <class VALUE_TYPE, int BLOCK_LENGTH> inline typename DequeImpUtil<VALUE_TYPE, BLOCK_LENGTH>::BlockPtr * DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::blockPtr() const { return d_blockPtr_p; } template <class VALUE_TYPE, int BLOCK_LENGTH> inline std::size_t DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::offsetInBlock() const { return d_value_p - blockBegin(); } template <class VALUE_TYPE, int BLOCK_LENGTH> inline std::size_t DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::remainingInBlock() const { return blockBegin() + BLOCK_LENGTH - d_value_p; } template <class VALUE_TYPE, int BLOCK_LENGTH> inline VALUE_TYPE * DequeIterator<VALUE_TYPE, BLOCK_LENGTH>::valuePtr() const { return d_value_p; } // --------------------------------- // class DequeIterator<VALUE_TYPE,1> // --------------------------------- // CREATORS template <class VALUE_TYPE> inline DequeIterator<VALUE_TYPE, 1>::DequeIterator() : d_blockPtr_p(0) , d_value_p(0) { } template <class VALUE_TYPE> inline DequeIterator<VALUE_TYPE, 1>::DequeIterator(BlockPtr *blockPtrPtr) : d_blockPtr_p(blockPtrPtr) , d_value_p(reinterpret_cast<VALUE_TYPE*>(*blockPtrPtr)) { } template <class VALUE_TYPE> inline DequeIterator<VALUE_TYPE, 1>::DequeIterator(BlockPtr *blockPtrPtr, VALUE_TYPE *valuePtr) : d_blockPtr_p(blockPtrPtr) , d_value_p(valuePtr) { BSLS_ASSERT_SAFE((*blockPtrPtr)->d_data == valuePtr); } // MANIPULATORS template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::operator++() { ++d_blockPtr_p; d_value_p = reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::operator--() { --d_blockPtr_p; d_value_p = reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::operator+=(std::ptrdiff_t offset) { d_blockPtr_p += offset; d_value_p = reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::operator-=(std::ptrdiff_t offset) { this->operator+=(-offset); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::nextBlock() { ++d_blockPtr_p; d_value_p = reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::previousBlock() { --d_blockPtr_p; d_value_p = reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::setBlock(BlockPtr *blockPtrPtr) { d_blockPtr_p = blockPtrPtr; d_value_p = reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::valuePtrDecrement() { // This should never be called for 'BLOCK_LENGTH' of 1 BSLS_ASSERT_SAFE(0); } template <class VALUE_TYPE> inline void DequeIterator<VALUE_TYPE, 1>::valuePtrIncrement() { // This should never be called for 'BLOCK_LENGTH' of 1 BSLS_ASSERT_SAFE(0); } // ACCESSORS template <class VALUE_TYPE> inline VALUE_TYPE& DequeIterator<VALUE_TYPE, 1>::operator*() const { return *d_value_p; } template <class VALUE_TYPE> inline DequeIterator<VALUE_TYPE, 1> DequeIterator<VALUE_TYPE, 1>::operator+(std::ptrdiff_t offset) const { return DequeIterator<VALUE_TYPE, 1>(d_blockPtr_p + offset); } template <class VALUE_TYPE> inline DequeIterator<VALUE_TYPE, 1> DequeIterator<VALUE_TYPE, 1>::operator-(std::ptrdiff_t offset) const { return DequeIterator<VALUE_TYPE, 1>(d_blockPtr_p - offset); } template <class VALUE_TYPE> inline std::ptrdiff_t DequeIterator<VALUE_TYPE, 1>::operator-( const DequeIterator<VALUE_TYPE, 1>& rhs) const { return d_blockPtr_p - rhs.d_blockPtr_p; } template <class VALUE_TYPE> inline VALUE_TYPE * DequeIterator<VALUE_TYPE, 1>::blockBegin() const { return reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p); } template <class VALUE_TYPE> inline VALUE_TYPE * DequeIterator<VALUE_TYPE, 1>::blockEnd() const { return reinterpret_cast<VALUE_TYPE*>(*d_blockPtr_p) + 1; } template <class VALUE_TYPE> inline typename DequeImpUtil<VALUE_TYPE, 1>::BlockPtr * DequeIterator<VALUE_TYPE, 1>::blockPtr() const { return d_blockPtr_p; } template <class VALUE_TYPE> inline std::size_t DequeIterator<VALUE_TYPE, 1>::offsetInBlock() const { return 0; } template <class VALUE_TYPE> inline std::size_t DequeIterator<VALUE_TYPE, 1>::remainingInBlock() const { return 1; } template <class VALUE_TYPE> inline VALUE_TYPE * DequeIterator<VALUE_TYPE, 1>::valuePtr() const { return d_value_p; } } // close package namespace #ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY // ============================================================================ // BACKWARD COMPATIBILITY // ============================================================================ #ifdef bslalg_DequeIterator #undef bslalg_DequeIterator #endif #define bslalg_DequeIterator bslalg::DequeIterator // This alias is defined for backward compatibility. #endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY } // close enterprise namespace // ============================================================================ // TYPE TRAITS // ============================================================================ namespace bsl { template <class VALUE_TYPE, int BLOCK_LENGTH> struct is_trivially_copyable<BloombergLP::bslalg::DequeIterator<VALUE_TYPE, BLOCK_LENGTH> > : true_type {}; } // close namespace bsl #endif // ---------------------------------------------------------------------------- // Copyright 2013 Bloomberg Finance L.P. // // 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. // ----------------------------- END-OF-FILE ----------------------------------