mdds
types.hpp
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*************************************************************************
3 *
4 * Copyright (c) 2021 Kohei Yoshida
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation
8 * files (the "Software"), to deal in the Software without
9 * restriction, including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following
13 * conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 ************************************************************************/
28
29#ifndef INCLUDED_MDDS_MULTI_TYPE_VECTOR_TYPES_2_HPP
30#define INCLUDED_MDDS_MULTI_TYPE_VECTOR_TYPES_2_HPP
31
32#include "../global.hpp"
33#include "./types_util.hpp"
34
35#include <algorithm>
36#include <cassert>
37#include <memory>
38#include <cstdint>
39#include <vector>
40
41#if defined(MDDS_UNIT_TEST) || defined(MDDS_MULTI_TYPE_VECTOR_DEBUG)
42#include <iostream>
43#include <sstream>
44using std::cerr;
45using std::cout;
46using std::endl;
47#endif
48
49namespace mdds { namespace mtv {
50
51using element_t = int;
52
53constexpr element_t element_type_empty = -1;
54
55constexpr element_t element_type_reserved_start = 0;
56constexpr element_t element_type_reserved_end = 49;
57
58constexpr element_t element_type_user_start = 50;
59
66enum class lu_factor_t : int
67{
68 none = 0,
69 lu4 = 4,
70 lu8 = 8,
71 lu16 = 16,
72 lu32 = 32,
73 sse2_x64 = 1 << 8,
74 sse2_x64_lu4 = 1 << 8 | 4,
75 sse2_x64_lu8 = 1 << 8 | 8,
76 sse2_x64_lu16 = 1 << 8 | 16,
77 avx2_x64 = 2 << 8,
78 avx2_x64_lu4 = 2 << 8 | 4,
79 avx2_x64_lu8 = 2 << 8 | 8,
80};
81
101enum class trace_method_t : int
102{
103 unspecified = 0,
104 accessor = 1,
105 accessor_with_pos_hint = 1 << 8 | 1,
106 mutator = 2,
107 mutator_with_pos_hint = 1 << 8 | 2,
108 constructor = 3,
109 destructor = 4
110};
111
116{
117 trace_method_t type = trace_method_t::unspecified;
118
124 const void* instance = nullptr;
125
127 const char* function_name = nullptr;
128
133 std::string function_args;
134
136 const char* filepath = nullptr;
137
139 int line_number = -1;
140};
141
146{
147public:
148 element_block_error(const std::string& msg) : mdds::general_error(msg)
149 {}
150};
151
153element_t get_block_type(const base_element_block&);
154
160{
161 friend element_t get_block_type(const base_element_block&);
162
163protected:
164 element_t type;
165 base_element_block(element_t _t) : type(_t)
166 {}
167};
168
174template<typename T, typename Allocator = std::allocator<T>>
176{
177 typedef std::vector<T, Allocator> store_type;
178 store_type m_vec;
179 size_t m_front_offset = 0; // number of elements removed from front of array
180public:
181 typedef typename store_type::value_type value_type;
182 typedef typename store_type::size_type size_type;
183 typedef typename store_type::difference_type difference_type;
184 typedef typename store_type::reference reference;
185 typedef typename store_type::const_reference const_reference;
186 typedef typename store_type::pointer pointer;
187 typedef typename store_type::const_pointer const_pointer;
188 typedef typename store_type::iterator iterator;
189 typedef typename store_type::reverse_iterator reverse_iterator;
190 typedef typename store_type::const_iterator const_iterator;
191 typedef typename store_type::const_reverse_iterator const_reverse_iterator;
192
193 delayed_delete_vector() : m_vec()
194 {}
195
196 delayed_delete_vector(size_t n, const T& val) : m_vec(n, val)
197 {}
198
199 delayed_delete_vector(size_t n) : m_vec(n)
200 {}
201
202 template<typename InputIt>
203 delayed_delete_vector(InputIt first, InputIt last) : m_vec(first, last)
204 {}
205
206 iterator begin() noexcept
207 {
208 return m_vec.begin() + m_front_offset;
209 }
210
211 iterator end() noexcept
212 {
213 return m_vec.end();
214 }
215
216 const_iterator begin() const noexcept
217 {
218 return m_vec.begin() + m_front_offset;
219 }
220
221 const_iterator end() const noexcept
222 {
223 return m_vec.end();
224 }
225
226 reverse_iterator rbegin() noexcept
227 {
228 return m_vec.rbegin();
229 }
230
231 const_reverse_iterator rbegin() const noexcept
232 {
233 return m_vec.rbegin();
234 }
235
236 reverse_iterator rend() noexcept
237 {
238 return m_vec.rend() - m_front_offset;
239 }
240
241 const_reverse_iterator rend() const noexcept
242 {
243 return m_vec.rend() - m_front_offset;
244 }
245
246 reference operator[](size_type pos)
247 {
248 return m_vec[pos + m_front_offset];
249 }
250
251 const_reference operator[](size_type pos) const
252 {
253 return m_vec[pos + m_front_offset];
254 }
255
256 reference at(size_type pos)
257 {
258 return m_vec.at(pos + m_front_offset);
259 }
260
261 const_reference at(size_type pos) const
262 {
263 return m_vec.at(pos + m_front_offset);
264 }
265
266 void push_back(const T& value)
267 {
268 m_vec.push_back(value);
269 }
270
271 iterator insert(iterator pos, const T& value)
272 {
273 return m_vec.insert(pos, value);
274 }
275
276 iterator insert(const_iterator pos, T&& value)
277 {
278 return m_vec.insert(pos, std::move(value));
279 }
280
281 template<typename InputIt>
282 void insert(iterator pos, InputIt first, InputIt last)
283 {
284 m_vec.insert(pos, first, last);
285 }
286
287 void resize(size_type count)
288 {
289 clear_removed();
290 m_vec.resize(count);
291 }
292
293 iterator erase(iterator pos)
294 {
295 if (pos == m_vec.begin() + m_front_offset)
296 {
297 ++m_front_offset;
298 return m_vec.begin() + m_front_offset;
299 }
300 else
301 return m_vec.erase(pos);
302 }
303
304 iterator erase(iterator first, iterator last)
305 {
306 return m_vec.erase(first, last);
307 }
308
309 size_type capacity() const noexcept
310 {
311 return m_vec.capacity();
312 }
313
314 void shrink_to_fit()
315 {
316 clear_removed();
317 m_vec.shrink_to_fit();
318 }
319
320 void reserve(size_type new_cap)
321 {
322 clear_removed();
323 m_vec.reserve(new_cap);
324 }
325
326 size_type size() const
327 {
328 return m_vec.size() - m_front_offset;
329 }
330
331 template<typename InputIt>
332 void assign(InputIt first, InputIt last)
333 {
334 clear_removed();
335 m_vec.assign(first, last);
336 }
337
338 T* data()
339 {
340 return m_vec.data() + m_front_offset;
341 }
342
343 const T* data() const
344 {
345 return m_vec.data() + m_front_offset;
346 }
347
348private:
349 void clear_removed()
350 {
351 m_vec.erase(m_vec.begin(), m_vec.begin() + m_front_offset);
352 m_front_offset = 0;
353 }
354};
355
356namespace detail {
357
358template<>
360{
361 using type = std::true_type;
362};
363
364} // namespace detail
365
366template<typename T>
367bool operator==(const delayed_delete_vector<T>& lhs, const delayed_delete_vector<T>& rhs)
368{
369 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
370}
371
372template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
374{
375public:
376 using store_type = StoreT<ValueT, std::allocator<ValueT>>;
377 static constexpr element_t block_type = TypeId;
378
379protected:
380 store_type m_array;
381
383 {}
384 element_block(size_t n) : base_element_block(TypeId), m_array(n)
385 {}
386 element_block(size_t n, const ValueT& val) : base_element_block(TypeId), m_array(n, val)
387 {}
388
389 template<typename Iter>
390 element_block(const Iter& it_begin, const Iter& it_end) : base_element_block(TypeId), m_array(it_begin, it_end)
391 {}
392
393public:
394 typedef typename store_type::iterator iterator;
395 typedef typename store_type::reverse_iterator reverse_iterator;
396 typedef typename store_type::const_iterator const_iterator;
397 typedef typename store_type::const_reverse_iterator const_reverse_iterator;
398 typedef ValueT value_type;
399
400 bool operator==(const Self& r) const
401 {
402 return m_array == r.m_array;
403 }
404
405 bool operator!=(const Self& r) const
406 {
407 return !operator==(r);
408 }
409
410 static const value_type& at(const base_element_block& block, typename store_type::size_type pos)
411 {
412 return get(block).m_array.at(pos);
413 }
414
415 static value_type& at(base_element_block& block, typename store_type::size_type pos)
416 {
417 return get(block).m_array.at(pos);
418 }
419
420 static value_type* data(base_element_block& block)
421 {
422 return get(block).m_array.data();
423 }
424
425 static typename store_type::size_type size(const base_element_block& block)
426 {
427 return get(block).m_array.size();
428 }
429
430 static iterator begin(base_element_block& block)
431 {
432 return get(block).m_array.begin();
433 }
434
435 static iterator end(base_element_block& block)
436 {
437 return get(block).m_array.end();
438 }
439
440 static const_iterator begin(const base_element_block& block)
441 {
442 return get(block).m_array.begin();
443 }
444
445 static const_iterator end(const base_element_block& block)
446 {
447 return get(block).m_array.end();
448 }
449
450 static const_iterator cbegin(const base_element_block& block)
451 {
452 return get(block).m_array.begin();
453 }
454
455 static const_iterator cend(const base_element_block& block)
456 {
457 return get(block).m_array.end();
458 }
459
460 static reverse_iterator rbegin(base_element_block& block)
461 {
462 return get(block).m_array.rbegin();
463 }
464
465 static reverse_iterator rend(base_element_block& block)
466 {
467 return get(block).m_array.rend();
468 }
469
470 static const_reverse_iterator rbegin(const base_element_block& block)
471 {
472 return get(block).m_array.rbegin();
473 }
474
475 static const_reverse_iterator rend(const base_element_block& block)
476 {
477 return get(block).m_array.rend();
478 }
479
480 static const_reverse_iterator crbegin(const base_element_block& block)
481 {
482 return get(block).m_array.rbegin();
483 }
484
485 static const_reverse_iterator crend(const base_element_block& block)
486 {
487 return get(block).m_array.rend();
488 }
489
490 static Self& get(base_element_block& block)
491 {
492#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
493 if (get_block_type(block) != TypeId)
494 {
495 std::ostringstream os;
496 os << "incorrect block type: expected block type=" << TypeId
497 << ", passed block type=" << get_block_type(block);
498 throw general_error(os.str());
499 }
500#endif
501 return static_cast<Self&>(block);
502 }
503
504 static const Self& get(const base_element_block& block)
505 {
506#ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
507 if (get_block_type(block) != TypeId)
508 {
509 std::ostringstream os;
510 os << "incorrect block type: expected block type=" << TypeId
511 << ", passed block type=" << get_block_type(block);
512 throw general_error(os.str());
513 }
514#endif
515 return static_cast<const Self&>(block);
516 }
517
518 static void set_value(base_element_block& blk, size_t pos, const ValueT& val)
519 {
520 get(blk).m_array[pos] = val;
521 }
522
523 static void get_value(const base_element_block& blk, size_t pos, ValueT& val)
524 {
525 val = get(blk).m_array[pos];
526 }
527
528 static value_type get_value(const base_element_block& blk, size_t pos)
529 {
530 return get(blk).m_array[pos];
531 }
532
533 static void append_value(base_element_block& blk, const ValueT& val)
534 {
535 get(blk).m_array.push_back(val);
536 }
537
538 static void prepend_value(base_element_block& blk, const ValueT& val)
539 {
540 store_type& blk2 = get(blk).m_array;
541 blk2.insert(blk2.begin(), val);
542 }
543
544 static Self* create_block(size_t init_size)
545 {
546 return new Self(init_size);
547 }
548
549 static void delete_block(const base_element_block* p)
550 {
551 delete static_cast<const Self*>(p);
552 }
553
554 static void resize_block(base_element_block& blk, size_t new_size)
555 {
556 store_type& st = get(blk).m_array;
557 st.resize(new_size);
558
559 // Test if the vector's capacity is larger than twice its current
560 // size, and if so, shrink its capacity to free up some memory.
561 if (new_size < (detail::get_block_capacity(st) / 2))
562 detail::shrink_to_fit(st);
563 }
564
565#ifdef MDDS_UNIT_TEST
566 static void print_block(const base_element_block& blk)
567 {
568 const store_type& blk2 = get(blk).m_array;
569 for (const auto& val : blk2)
570 std::cout << val << " ";
571
572 std::cout << std::endl;
573 }
574#else
575 static void print_block(const base_element_block&)
576 {}
577#endif
578
579 static void erase_value(base_element_block& blk, size_t pos)
580 {
581 store_type& blk2 = get(blk).m_array;
582 blk2.erase(blk2.begin() + pos);
583 }
584
585 static void erase_values(base_element_block& blk, size_t pos, size_t size)
586 {
587 store_type& blk2 = get(blk).m_array;
588 blk2.erase(blk2.begin() + pos, blk2.begin() + pos + size);
589 }
590
591 static void append_block(base_element_block& dest, const base_element_block& src)
592 {
593 store_type& d = get(dest).m_array;
594 const store_type& s = get(src).m_array;
595 d.insert(d.end(), s.begin(), s.end());
596 }
597
598 static void append_values_from_block(
599 base_element_block& dest, const base_element_block& src, size_t begin_pos, size_t len)
600 {
601 store_type& d = get(dest).m_array;
602 const store_type& s = get(src).m_array;
603 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
604 detail::reserve(d, d.size() + len);
605 d.insert(d.end(), its.first, its.second);
606 }
607
608 static void assign_values_from_block(
609 base_element_block& dest, const base_element_block& src, size_t begin_pos, size_t len)
610 {
611 store_type& d = get(dest).m_array;
612 const store_type& s = get(src).m_array;
613 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
614 d.assign(its.first, its.second);
615 }
616
617 static void prepend_values_from_block(
618 base_element_block& dest, const base_element_block& src, size_t begin_pos, size_t len)
619 {
620 store_type& d = get(dest).m_array;
621 const store_type& s = get(src).m_array;
622 std::pair<const_iterator, const_iterator> its = get_iterator_pair(s, begin_pos, len);
623 detail::reserve(d, d.size() + len);
624 d.insert(d.begin(), its.first, its.second);
625 }
626
627 static void swap_values(base_element_block& blk1, base_element_block& blk2, size_t pos1, size_t pos2, size_t len)
628 {
629 store_type& st1 = get(blk1).m_array;
630 store_type& st2 = get(blk2).m_array;
631 assert(pos1 + len <= st1.size());
632 assert(pos2 + len <= st2.size());
633
634 typename store_type::iterator it1 = st1.begin(), it2 = st2.begin();
635 std::advance(it1, pos1);
636 std::advance(it2, pos2);
637
638 for (size_t i = 0; i < len; ++i, ++it1, ++it2)
639 {
640 value_type v1 = *it1, v2 = *it2;
641 *it1 = v2;
642 *it2 = v1;
643 }
644 }
645
646 static bool equal_block(const base_element_block& left, const base_element_block& right)
647 {
648 return get(left) == get(right);
649 }
650
651 template<typename Iter>
652 static void set_values(base_element_block& block, size_t pos, const Iter& it_begin, const Iter& it_end)
653 {
654 store_type& d = get(block).m_array;
655 typename store_type::iterator it_dest = d.begin();
656 std::advance(it_dest, pos);
657 for (Iter it = it_begin; it != it_end; ++it, ++it_dest)
658 *it_dest = *it;
659 }
660
661 template<typename Iter>
662 static void append_values(base_element_block& block, const Iter& it_begin, const Iter& it_end)
663 {
664 store_type& d = get(block).m_array;
665 typename store_type::iterator it = d.end();
666 d.insert(it, it_begin, it_end);
667 }
668
669 template<typename Iter>
670 static void prepend_values(base_element_block& block, const Iter& it_begin, const Iter& it_end)
671 {
672 store_type& d = get(block).m_array;
673 d.insert(d.begin(), it_begin, it_end);
674 }
675
676 template<typename Iter>
677 static void assign_values(base_element_block& dest, const Iter& it_begin, const Iter& it_end)
678 {
679 store_type& d = get(dest).m_array;
680 d.assign(it_begin, it_end);
681 }
682
683 template<typename Iter>
684 static void insert_values(base_element_block& block, size_t pos, const Iter& it_begin, const Iter& it_end)
685 {
686 store_type& blk = get(block).m_array;
687 blk.insert(blk.begin() + pos, it_begin, it_end);
688 }
689
690 static size_t capacity(const base_element_block& block)
691 {
692 const store_type& blk = get(block).m_array;
693 return detail::get_block_capacity(blk);
694 }
695
696 static void reserve(base_element_block& block, std::size_t size)
697 {
698 store_type& blk = get(block).m_array;
699 detail::reserve(blk, size);
700 }
701
702 static void shrink_to_fit(base_element_block& block)
703 {
704 store_type& blk = get(block).m_array;
705 detail::shrink_to_fit(blk);
706 }
707
708private:
709 static std::pair<const_iterator, const_iterator> get_iterator_pair(
710 const store_type& array, size_t begin_pos, size_t len)
711 {
712 assert(begin_pos + len <= array.size());
713 const_iterator it = array.begin();
714 std::advance(it, begin_pos);
715 const_iterator it_end = it;
716 std::advance(it_end, len);
717 return std::pair<const_iterator, const_iterator>(it, it_end);
718 }
719};
720
721template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
722class copyable_element_block : public element_block<Self, TypeId, ValueT, StoreT>
723{
725
726protected:
728 {}
729 copyable_element_block(size_t n) : base_type(n)
730 {}
731 copyable_element_block(size_t n, const ValueT& val) : base_type(n, val)
732 {}
733
734 template<typename Iter>
735 copyable_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
736 {}
737
738public:
739 using base_type::get;
740
741 static Self* clone_block(const base_element_block& blk)
742 {
743 // Use copy constructor to copy the data.
744 return new Self(get(blk));
745 }
746};
747
748template<typename Self, element_t TypeId, typename ValueT, template<typename, typename> class StoreT>
749class noncopyable_element_block : public element_block<Self, TypeId, ValueT, StoreT>
750{
752
753protected:
755 {}
757 {}
758 noncopyable_element_block(size_t n, const ValueT& val) : base_type(n, val)
759 {}
760
761 template<typename Iter>
762 noncopyable_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
763 {}
764
765public:
767 noncopyable_element_block& operator=(const noncopyable_element_block&) = delete;
768
769 static Self* clone_block(const base_element_block&)
770 {
771 throw element_block_error("attempted to clone a noncopyable element block.");
772 }
773};
774
782inline element_t get_block_type(const base_element_block& blk)
783{
784 return blk.type;
785}
786
791template<element_t TypeId, typename ValueT, template<typename, typename> class StoreT = delayed_delete_vector>
793 : public copyable_element_block<default_element_block<TypeId, ValueT, StoreT>, TypeId, ValueT, StoreT>
794{
797
799 {}
800 default_element_block(size_t n) : base_type(n)
801 {}
802 default_element_block(size_t n, const ValueT& val) : base_type(n, val)
803 {}
804
805 template<typename Iter>
806 default_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
807 {}
808
809 static self_type* create_block_with_value(size_t init_size, const ValueT& val)
810 {
811 return new self_type(init_size, val);
812 }
813
814 template<typename Iter>
815 static self_type* create_block_with_values(const Iter& it_begin, const Iter& it_end)
816 {
817 return new self_type(it_begin, it_end);
818 }
819
820 static void overwrite_values(base_element_block&, size_t, size_t)
821 {
822 // Do nothing.
823 }
824};
825
830template<element_t TypeId, typename ValueT, template<typename, typename> class StoreT = delayed_delete_vector>
832 : public copyable_element_block<managed_element_block<TypeId, ValueT, StoreT>, TypeId, ValueT*, StoreT>
833{
836
837 using base_type::get;
838 using base_type::m_array;
839 using base_type::reserve;
840 using base_type::set_value;
841
843 {}
844 managed_element_block(size_t n) : base_type(n)
845 {}
847 {
848 detail::reserve(m_array, r.m_array.size());
849 for (const auto& v : r.m_array)
850 m_array.push_back(new ValueT(*v));
851 }
852
853 template<typename Iter>
854 managed_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
855 {}
856
858 {
859 std::for_each(m_array.begin(), m_array.end(), std::default_delete<ValueT>());
860 }
861
862 static self_type* create_block_with_value(size_t init_size, ValueT* val)
863 {
864 // Managed blocks don't support initialization with value.
865 if (init_size > 1)
866 throw general_error("You can't create a managed block with initial value.");
867
868 std::unique_ptr<self_type> blk = std::make_unique<self_type>(init_size);
869 if (init_size == 1)
870 set_value(*blk, 0, val);
871
872 return blk.release();
873 }
874
875 template<typename Iter>
876 static self_type* create_block_with_values(const Iter& it_begin, const Iter& it_end)
877 {
878 return new self_type(it_begin, it_end);
879 }
880
881 static void overwrite_values(base_element_block& block, size_t pos, size_t len)
882 {
883 managed_element_block& blk = get(block);
884 typename managed_element_block::store_type::iterator it = blk.m_array.begin() + pos;
885 typename managed_element_block::store_type::iterator it_end = it + len;
886 std::for_each(it, it_end, std::default_delete<ValueT>());
887 }
888};
889
890template<element_t TypeId, typename ValueT, template<typename, typename> class StoreT = delayed_delete_vector>
893 noncopyable_managed_element_block<TypeId, ValueT, StoreT>, TypeId, ValueT*, StoreT>
894{
897
898 using base_type::get;
899 using base_type::m_array;
900 using base_type::set_value;
901
903 {}
905 {}
906
907 template<typename Iter>
908 noncopyable_managed_element_block(const Iter& it_begin, const Iter& it_end) : base_type(it_begin, it_end)
909 {}
910
912 {
913 std::for_each(m_array.begin(), m_array.end(), std::default_delete<ValueT>());
914 }
915
916 static self_type* create_block_with_value(size_t init_size, ValueT* val)
917 {
918 // Managed blocks don't support initialization with value.
919 if (init_size > 1)
920 throw general_error("You can't create a managed block with initial value.");
921
922 std::unique_ptr<self_type> blk = std::make_unique<self_type>(init_size);
923 if (init_size == 1)
924 set_value(*blk, 0, val);
925
926 return blk.release();
927 }
928
929 template<typename Iter>
930 static self_type* create_block_with_values(const Iter& it_begin, const Iter& it_end)
931 {
932 return new self_type(it_begin, it_end);
933 }
934
935 static void overwrite_values(base_element_block& block, size_t pos, size_t len)
936 {
937 noncopyable_managed_element_block& blk = get(block);
938 typename noncopyable_managed_element_block::store_type::iterator it = blk.m_array.begin() + pos;
939 typename noncopyable_managed_element_block::store_type::iterator it_end = it + len;
940 std::for_each(it, it_end, std::default_delete<ValueT>());
941 }
942};
943
944namespace detail {
945
946template<typename Blk>
947bool get_block_element_at(const mdds::mtv::base_element_block& data, size_t offset, std::true_type)
948{
949 auto it = Blk::cbegin(data);
950 std::advance(it, offset);
951 return *it;
952}
953
954template<typename Blk>
955typename Blk::value_type get_block_element_at(const mdds::mtv::base_element_block& data, size_t offset, std::false_type)
956{
957 return Blk::at(data, offset);
958}
959
960template<typename Blk>
961typename Blk::value_type get_block_element_at(const mdds::mtv::base_element_block& data, size_t offset)
962{
963 typename mdds::mtv::detail::has_std_vector_bool_store<Blk>::type v;
964 return get_block_element_at<Blk>(data, offset, v);
965}
966
967} // namespace detail
968
969}} // namespace mdds::mtv
970
971#endif
972
973/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: global.hpp:84
Definition: types.hpp:160
friend element_t get_block_type(const base_element_block &)
Definition: types.hpp:782
Definition: types.hpp:723
Definition: types.hpp:176
Definition: types.hpp:146
Definition: types.hpp:374
Definition: types.hpp:750
Definition: types.hpp:794
Definition: types_util.hpp:147
Definition: types.hpp:833
Definition: types.hpp:116
std::string function_args
Definition: types.hpp:133
const char * function_name
Definition: types.hpp:127
int line_number
Definition: types.hpp:139
const void * instance
Definition: types.hpp:124
const char * filepath
Definition: types.hpp:136