nlib
Nlist.h
[詳解]
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_NLIST_H_
17 #define INCLUDE_NN_NLIB_NLIST_H_
18 
19 #include <string.h>
20 #include <utility>
21 #include <algorithm>
22 #include <iterator>
23 #include <memory>
24 
25 #include "nn/nlib/Config.h"
26 #include "nn/nlib/Swap.h"
27 #include "nn/nlib/TypeTraits.h"
28 
29 NLIB_NAMESPACE_BEGIN
30 
31 template<class T, class AL>
32 class Nlist;
33 
34 namespace nlist {
35 
36 class NLIB_VIS_PUBLIC NlistBase {
37  protected:
38  struct Blk {
39  Blk* next;
40  void* item;
41  };
42 
43  protected:
44  NLIB_CEXPR NlistBase() NLIB_NOEXCEPT : curblk_(nullptr),
45  curlevel_(0),
46  curidx_(0),
47  firstblk_(nullptr) {}
48 #ifdef __cpp_rvalue_references
49  NlistBase(NlistBase&& rhs) NLIB_NOEXCEPT : curblk_(rhs.curblk_),
50  curlevel_(rhs.curlevel_),
51  curidx_(rhs.curidx_),
52  firstblk_(rhs.firstblk_) {
53  rhs.curblk_ = nullptr;
54  rhs.curlevel_ = 0U;
55  rhs.curidx_ = 0U;
56  rhs.firstblk_ = nullptr;
57  }
58  NlistBase& operator=(NlistBase&& rhs) NLIB_NOEXCEPT {
59  curblk_ = rhs.curblk_;
60  curlevel_ = rhs.curlevel_;
61  curidx_ = rhs.curidx_;
62  firstblk_ = rhs.firstblk_;
63  rhs.curblk_ = nullptr;
64  rhs.curlevel_ = 0U;
65  rhs.curidx_ = 0U;
66  rhs.firstblk_ = nullptr;
67  return *this;
68  }
69 #endif
70  NlistBase(NlistBase& rhs, move_tag) NLIB_NOEXCEPT : curblk_(rhs.curblk_),
71  curlevel_(rhs.curlevel_),
72  curidx_(rhs.curidx_),
73  firstblk_(rhs.firstblk_) {
74  rhs.curblk_ = nullptr;
75  rhs.curlevel_ = 0U;
76  rhs.curidx_ = 0U;
77  rhs.firstblk_ = nullptr;
78  }
79  NlistBase& assign(NlistBase& rhs, move_tag) NLIB_NOEXCEPT {
80  curblk_ = rhs.curblk_;
81  curlevel_ = rhs.curlevel_;
82  curidx_ = rhs.curidx_;
83  firstblk_ = rhs.firstblk_;
84  rhs.curblk_ = nullptr;
85  rhs.curlevel_ = 0U;
86  rhs.curidx_ = 0U;
87  rhs.firstblk_ = nullptr;
88  return *this;
89  }
90  static size_t BlkBaseIdx(size_t level) NLIB_NOEXCEPT { return 8 * ((1 << level) - 1); }
91  static size_t BlkSize(size_t level) NLIB_NOEXCEPT { return 8 * (1 << level); }
92  Blk* LastBlock(size_t* level) const NLIB_NOEXCEPT;
93  bool ConfirmBack() const NLIB_NOEXCEPT;
94  void ClearSimple() NLIB_NOEXCEPT {
95  curlevel_ = 0;
96  curidx_ = 0;
97  curblk_ = firstblk_;
98  }
99  const Blk* AtSub(size_t n, size_t* base) const NLIB_NOEXCEPT;
100 
101  protected:
102  mutable Blk* curblk_;
103  mutable size_t curlevel_;
104  mutable size_t curidx_;
105  mutable Blk* firstblk_;
106 
107  private:
109 };
110 
111 template<class T>
112 class NlistConstIterator;
113 template<class T>
114 class NlistIterator;
115 
116 template<class T>
117 class NlistBaseT : public NlistBase {
118  public:
119  typedef T& reference;
120  typedef const T& const_reference;
121  typedef NlistIterator<T> iterator;
122  typedef NlistConstIterator<T> const_iterator;
123  typedef size_t size_type;
124  typedef T value_type;
125  typedef T* pointer;
126  typedef const T* const_pointer;
127  typedef ptrdiff_t difference_type;
128 
129  protected:
130  NLIB_CEXPR NlistBaseT() {}
131 #ifdef __cpp_rvalue_references
132 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
133  NlistBaseT(NlistBaseT&& rhs) = default;
134  NlistBaseT& operator=(NlistBaseT&& rhs) = default;
135 #else
136  NlistBaseT(NlistBaseT&& rhs) NLIB_NOEXCEPT : NlistBase(std::move(rhs)) {}
137  NlistBaseT& operator=(NlistBaseT&& rhs) NLIB_NOEXCEPT {
138  NlistBase::operator=(std::move(rhs));
139  return *this;
140  }
141 #endif
142 #endif
143  NlistBaseT(NlistBaseT& rhs, move_tag) NLIB_NOEXCEPT : NlistBase(rhs, move_tag()) {}
144  NlistBaseT& assign(NlistBaseT& rhs, move_tag) NLIB_NOEXCEPT {
145  NlistBase::assign(rhs, move_tag());
146  return *this;
147  }
148 
149  static T* GetItem(Blk* blk) NLIB_NOEXCEPT { return static_cast<T*>(blk->item); }
150  static const T* GetItem(const Blk* blk) NLIB_NOEXCEPT {
151  return static_cast<const T*>(blk->item);
152  }
153  T* At(size_type n) const NLIB_NOEXCEPT {
154  size_type base;
155  const Blk* p = this->AtSub(n, &base);
156  return p ? const_cast<T*>(&(GetItem(p)[n - base])) : nullptr;
157  }
158  iterator Begin() NLIB_NOEXCEPT { return iterator(this, TrueType()); }
159  iterator End() NLIB_NOEXCEPT { return iterator(this, FalseType()); }
160  const_iterator Begin() const NLIB_NOEXCEPT { return const_iterator(this, TrueType()); }
161  const_iterator End() const NLIB_NOEXCEPT { return const_iterator(this, FalseType()); }
162 
163  private:
164  NLIB_DISALLOW_COPY_AND_ASSIGN(NlistBaseT);
165  friend class NlistConstIterator<T>;
166  friend class NlistIterator<T>;
167 };
168 
169 template<class T>
170 class NlistConstIterator : public std::iterator<std::forward_iterator_tag, T> {
171  private:
172  typedef NlistBaseT<T> ContainerType;
173  typedef typename ContainerType::Blk Blk;
174 
175  public:
176  typedef typename std::iterator<std::forward_iterator_tag, T> BaseType;
177  typedef typename BaseType::iterator_category iterator_category;
178  typedef typename BaseType::value_type value_type;
179  typedef typename BaseType::difference_type difference_type;
180  typedef typename BaseType::pointer pointer;
181  typedef typename BaseType::reference reference;
182 
183  public:
184  NLIB_CEXPR NlistConstIterator() NLIB_NOEXCEPT : idx_(0),
185  elemptr_(nullptr),
186  blkend_(nullptr),
187  blk_(nullptr) {}
188 
189  protected:
190  NlistConstIterator(const ContainerType* p, TrueType) NLIB_NOEXCEPT {
191  ContainerType* rhs = const_cast<ContainerType*>(p);
192  idx_ = 0;
193  blk_ = rhs->firstblk_;
194  elemptr_ = GetItem(blk_);
195  blkend_ = elemptr_ + 8;
196  }
197  NlistConstIterator(const ContainerType* p, FalseType) NLIB_NOEXCEPT {
198  ContainerType* rhs = const_cast<ContainerType*>(p);
199  idx_ = rhs->BlkBaseIdx(rhs->curlevel_) + rhs->curidx_;
200  blk_ = rhs->curblk_;
201  elemptr_ = &(GetItem(blk_)[rhs->curidx_]);
202  blkend_ = GetItem(blk_) + rhs->BlkSize(rhs->curlevel_);
203  if (elemptr_ == blkend_) this->Normalize();
204  }
205 
206  public:
207  const T& operator*() const NLIB_NOEXCEPT { return *elemptr_; }
208  const T* operator->() const NLIB_NOEXCEPT { return elemptr_; }
209  NlistConstIterator& operator++() NLIB_NOEXCEPT {
210  NLIB_ASSERT(elemptr_ != blkend_);
211  ++idx_;
212  if (++elemptr_ == blkend_) this->Normalize();
213  return *this;
214  }
215  NlistConstIterator operator++(int) NLIB_NOEXCEPT {
216  NlistConstIterator rval(*this);
217  this->operator++();
218  return rval;
219  }
220  bool operator==(const NlistConstIterator& rhs) const NLIB_NOEXCEPT {
221  return idx_ == rhs.idx_ && elemptr_ == rhs.elemptr_;
222  }
223  bool operator!=(const NlistConstIterator& rhs) const NLIB_NOEXCEPT { return !operator==(rhs); }
224  void Advance(difference_type n) NLIB_NOEXCEPT;
225  difference_type Distance(NlistConstIterator to) const NLIB_NOEXCEPT { return to.idx_ - idx_; }
226 
227  private:
228  static T* GetItem(Blk* blk) NLIB_NOEXCEPT { return static_cast<T*>(blk->item); }
229  static const T* GetItem(const Blk* blk) NLIB_NOEXCEPT {
230  return reinterpret_cast<const T*>(blk->item);
231  }
232  bool Normalize() NLIB_NOEXCEPT;
233 
234  private:
235  size_t idx_;
236  T* elemptr_;
237  T* blkend_;
238  Blk* blk_;
239  friend class NlistBaseT<T>;
240 };
241 
242 template<class T>
243 bool NlistConstIterator<T>::Normalize() NLIB_NOEXCEPT {
244  if (blk_ && blk_->next) {
245  Blk* next = blk_->next;
246  size_t next_size = 2 * static_cast<size_t>(blkend_ - GetItem(blk_));
247  T* next_elemptr = GetItem(next);
248  T* next_end = next_elemptr + next_size;
249  blk_ = next;
250  elemptr_ = next_elemptr;
251  blkend_ = next_end;
252  return true;
253  }
254  return false;
255 }
256 
257 template<class T>
258 void NlistConstIterator<T>::Advance(difference_type n) NLIB_NOEXCEPT {
259  while (elemptr_ + n >= blkend_) {
260  n -= blkend_ - elemptr_;
261  idx_ += blkend_ - elemptr_;
262  elemptr_ = blkend_;
263  if (!this->Normalize()) return;
264  }
265  elemptr_ += n;
266  idx_ += n;
267 }
268 
269 template<class T>
270 class NlistIterator : public NlistConstIterator<T> {
271  private:
272  typedef NlistBaseT<T> ContainerType;
273  typedef typename ContainerType::Blk Blk;
274  typedef NlistConstIterator<T> MyBase;
275 
276  public:
277  typedef typename NlistConstIterator<T>::BaseType BaseType;
278  typedef typename BaseType::iterator_category iterator_category;
279  typedef typename BaseType::value_type value_type;
280  typedef typename BaseType::difference_type difference_type;
281  typedef typename BaseType::pointer pointer;
282  typedef typename BaseType::reference reference;
283 
284  public:
285  NLIB_CEXPR NlistIterator() NLIB_NOEXCEPT : MyBase() {}
286 
287  private:
288  NlistIterator(const ContainerType* p, TrueType) NLIB_NOEXCEPT : MyBase(p, TrueType()) {}
289  NlistIterator(const ContainerType* p, FalseType) NLIB_NOEXCEPT : MyBase(p, FalseType()) {}
290 
291  public:
292  T& operator*() const NLIB_NOEXCEPT {
293  const MyBase* tmp = static_cast<const MyBase*>(this);
294  return const_cast<T&>(**tmp);
295  }
296  T* operator->() const NLIB_NOEXCEPT {
297  const MyBase* tmp = static_cast<const MyBase*>(this);
298  return const_cast<T*>(tmp->operator->());
299  }
300  NlistIterator& operator++() NLIB_NOEXCEPT {
301  MyBase* tmp = static_cast<MyBase*>(this);
302  ++(*tmp);
303  return *this;
304  }
305  NlistIterator operator++(int) NLIB_NOEXCEPT {
306  NlistIterator rval(*this);
307  ++(*this);
308  return rval;
309  }
310  bool operator==(const NlistIterator& rhs) const NLIB_NOEXCEPT {
311  const MyBase* tmp = static_cast<const MyBase*>(this);
312  const MyBase* tmp2 = static_cast<const MyBase*>(&rhs);
313  return *tmp == *tmp2;
314  }
315  bool operator!=(const NlistIterator& rhs) const NLIB_NOEXCEPT { return !operator==(rhs); }
316  difference_type Distance(NlistIterator to) const NLIB_NOEXCEPT {
317  const MyBase* tmp = static_cast<const MyBase*>(this);
318  const MyBase* tmp2 = static_cast<const MyBase*>(&to);
319  return tmp->Distance(*tmp2);
320  }
321 
322  private:
323  friend class NlistBaseT<T>;
324 };
325 
326 template<bool is_empty, class AL>
327 class NlistAlloc {
328  public:
329  NlistAlloc() NLIB_NOEXCEPT : alloc_(AL()) {}
330  explicit NlistAlloc(const AL& al) NLIB_NOEXCEPT : alloc_(al) {}
331 
332  protected:
333  AL& _GetNlistAlloc() const NLIB_NOEXCEPT { return const_cast<AL&>(alloc_); }
334  void _SwapNlistAlloc(NlistAlloc& rhs) NLIB_NOEXCEPT {
335  using std::swap;
336  swap(alloc_, rhs.alloc_);
337  }
338 #ifdef __cpp_rvalue_references
339 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
340  NlistAlloc(NlistAlloc&& rhs) = default;
341  NlistAlloc& operator=(NlistAlloc&& rhs) = default;
342 #else
343  NlistAlloc(NlistAlloc&& rhs) NLIB_NOEXCEPT : alloc_(std::move(rhs.alloc_)) {}
344  NlistAlloc& operator=(NlistAlloc&& rhs) NLIB_NOEXCEPT {
345  alloc_ = std::move(rhs.alloc_);
346  return *this;
347  }
348 #endif
349 #endif
350  NlistAlloc(NlistAlloc& rhs, move_tag) NLIB_NOEXCEPT : alloc_() {
351  using std::swap;
352  swap(alloc_, rhs.alloc_);
353  }
354  NlistAlloc& assign(NlistAlloc& rhs, move_tag) NLIB_NOEXCEPT {
355  using std::swap;
356  AL x(*this, move_tag());
357  swap(alloc_, rhs.alloc_);
358  return *this;
359  }
360 
361  private:
362  AL alloc_;
363 };
364 
365 template<class AL>
366 class NlistAlloc<true, AL> {
367  public:
368  NlistAlloc() NLIB_NOEXCEPT {}
369  explicit NlistAlloc(const AL& al) NLIB_NOEXCEPT { NLIB_UNUSED(al); }
370 
371  protected:
372  AL _GetNlistAlloc() const NLIB_NOEXCEPT { return AL(); }
373  void _SwapNlistAlloc(NlistAlloc& rhs) NLIB_NOEXCEPT { NLIB_UNUSED(rhs); }
374 #ifdef __cpp_rvalue_references
375  NlistAlloc(NlistAlloc&&) NLIB_NOEXCEPT {}
376  NlistAlloc& operator=(NlistAlloc&&) NLIB_NOEXCEPT { return *this; }
377 #endif
378  NlistAlloc(NlistAlloc&, move_tag) NLIB_NOEXCEPT {}
379  NlistAlloc& assign(NlistAlloc&, move_tag) NLIB_NOEXCEPT { return *this; }
380 };
381 
382 } // namespace nlist
383 
384 template<class T, class AL = std::allocator<char> >
385 class Nlist NLIB_FINAL : public nlist::NlistBaseT<T>,
386  public nlist::NlistAlloc<IsEmpty<AL>::value, AL> {
387  // NOTE:
388  // To develop custom allocators:
389  //
390  // Nlist uses only the subset of std::allocator<T>.
391  // 1) rebind() is not used. the custom allocator does not have to be a class template.
392  // 2) construct(), destroy() are not used.
393  //
394  // You have to implement:
395  // a) void* allocate(size_t nbytes);
396  // b) void deallocate(void* ptr, size_t nbytes);
397  // allocate has to return 8 bytes aligned memory.
398  // And the custom allocator cannot have non-static data members.
399  /*
400  class MyAllocator
401  {
402  public:
403  MyAllocator();
404  MyAllocator(const MyAllocator& rhs);
405  void* allocate(size_t nbytes, void*);
406  void deallocate(void* p, size_t nbytes);
407  };
408  */
409 
410  private:
411  typedef typename nlist::NlistBaseT<T> BaseType;
412  typedef typename nlist::NlistAlloc<IsEmpty<AL>::value, AL> AllocType;
413  using BaseType::curblk_;
414  using BaseType::curidx_;
415  using BaseType::curlevel_;
416  using BaseType::firstblk_;
417  using BaseType::ConfirmBack;
418  using BaseType::ClearSimple;
419  using BaseType::BlkBaseIdx;
420  using BaseType::BlkSize;
421  using BaseType::GetItem;
422  using BaseType::Begin;
423  using BaseType::End;
424  typedef typename BaseType::Blk Blk;
425 
426  public:
428  typedef AL allocator_type;
429  typedef typename BaseType::size_type size_type;
430  typedef typename BaseType::difference_type difference_type;
431  typedef typename BaseType::reference reference;
433  typedef typename BaseType::pointer pointer;
435  typedef typename BaseType::iterator iterator;
436  typedef typename BaseType::const_iterator const_iterator;
437 
438  public:
439  Nlist() NLIB_NOEXCEPT : AllocType(AL()) {}
440  explicit Nlist(const AL& al) NLIB_NOEXCEPT : AllocType(al) {}
441  ~Nlist() NLIB_NOEXCEPT;
442 #ifdef __cpp_rvalue_references
443 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
444  Nlist(Nlist&& rhs) = default;
445 #else
446  Nlist(Nlist&& rhs) NLIB_NOEXCEPT : BaseType(std::move(rhs)), AllocType(std::move(rhs)) {}
447 #endif
449  this->clear();
450  this->DeallocBlkList(firstblk_, 0);
451  BaseType::operator =(std::move(rhs));
452  AllocType::operator=(std::move(rhs));
453  return *this;
454  }
455 #endif
456  Nlist(Nlist& rhs, move_tag) NLIB_NOEXCEPT : BaseType(rhs, move_tag()),
457  AllocType(rhs, move_tag()) {}
459  this->clear();
460  this->DeallocBlkList(firstblk_, 0);
461  BaseType::assign(rhs, move_tag());
462  AllocType::assign(rhs, move_tag());
463  return *this;
464  }
465  size_type size() const NLIB_NOEXCEPT { return BlkBaseIdx(curlevel_) + curidx_; }
466  size_type capacity() const NLIB_NOEXCEPT {
467  size_type lv;
468  return (nullptr != this->LastBlock(&lv)) ? BlkBaseIdx(lv + 1) : 0;
469  }
470  bool empty() const NLIB_NOEXCEPT { return curlevel_ == 0 && curidx_ == 0; }
471  bool resize(size_type n) NLIB_NOEXCEPT {
472  return Resize(n, typename IsTriviallyDefaultConstructible<T>::type());
473  }
474  bool reserve(size_type n) NLIB_NOEXCEPT;
475  pointer push_back() {
476  void* p = this->PushBack();
477  if (!p) return nullptr;
478  pointer ptr = MyCtor(p, typename IsTriviallyDefaultConstructible<T>::type()); // may throw
479  ++curidx_;
480  return ptr;
481  }
482 #ifdef __cpp_rvalue_references
483  pointer push_back(T&& rhs) NLIB_NOEXCEPT {
484 #if defined(NLIB_HAS_NATIVE_TYPETRAITS) && !defined(NLIB_HAS_TR1_TYPETRAITS) && \
485  (!defined(_MSC_VER) || _MSC_VER > 1800)
486 #ifdef __cpp_exceptions
487  // with -fno-exceptions, MpObjectKv cannot compile
488  NLIB_STATIC_ASSERT(std::is_nothrow_move_constructible<T>::value);
489 #endif
490 #endif
491  void* p = this->PushBack();
492  if (!p) return nullptr;
493  pointer ptr = new (p) T(std::forward<T>(rhs));
494  ++curidx_;
495  return ptr;
496  }
497 #endif
498  pointer push_back(const T& rhs) {
499  void* p = this->PushBack();
500  if (!p) return nullptr;
501  pointer ptr = new (p) T(rhs); // may throw
502  ++curidx_;
503  return ptr;
504  }
506  return this->pop_back_(typename IsTriviallyDestructible<T>::type());
507  }
508  void clear() NLIB_NOEXCEPT { Clear(typename IsTriviallyDestructible<T>::type()); }
509  allocator_type get_allocator() const NLIB_NOEXCEPT { return AllocType::_GetNlistAlloc(); }
510 
511  reference back() {
512  NLIB_ASSERT(!this->empty());
513  if (curidx_ == 0) ConfirmBack();
514  return GetItem(curblk_)[curidx_ - 1];
515  }
516  const_reference back() const {
517  NLIB_ASSERT(!this->empty());
518  if (curidx_ == 0) ConfirmBack();
519  return GetItem(curblk_)[curidx_ - 1];
520  }
521  reference front() {
522  NLIB_ASSERT(!this->empty());
523  return GetItem(firstblk_)[0];
524  }
525  const_reference front() const {
526  NLIB_ASSERT(!this->empty());
527  return GetItem(firstblk_)[0];
528  }
529  reference operator[](size_type n) {
530  NLIB_ASSERT(n < this->size());
531  return *this->At(n);
532  }
533  const_reference operator[](size_type n) const {
534  NLIB_ASSERT(n < this->size());
535  return *this->At(n);
536  }
537  iterator begin() NLIB_NOEXCEPT {
538  if (!firstblk_ && !ConfirmFirstBlk()) return iterator();
539  return Begin();
540  }
541  const_iterator begin() const NLIB_NOEXCEPT {
542  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
543  return Begin();
544  }
545  const_iterator cbegin() const NLIB_NOEXCEPT {
546  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
547  return Begin();
548  }
549 
550  iterator end() NLIB_NOEXCEPT {
551  if (!firstblk_ && !ConfirmFirstBlk()) return iterator();
552  return End();
553  }
554  const_iterator end() const NLIB_NOEXCEPT {
555  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
556  return End();
557  }
558  const_iterator cend() const NLIB_NOEXCEPT {
559  if (!firstblk_ && !ConfirmFirstBlk()) return const_iterator();
560  return End();
561  }
562 
564  if (!curblk_) return;
565  Blk* p = curblk_->next;
566  curblk_->next = nullptr;
567  DeallocBlkList(p, static_cast<int>(curlevel_ + 1));
568  }
569 #if defined(__cpp_rvalue_references) && defined(__cpp_variadic_templates)
570  template<class... Args>
571  pointer EmplaceBack(Args&&... args) {
572  void* p = this->PushBack();
573  if (!p) return nullptr;
574  pointer ptr = new (p) T(std::forward<Args>(args)...); // may throw
575  ++curidx_;
576  return ptr;
577  }
578 #else
579  template<class A1>
580  pointer EmplaceBack(const A1& a1) {
581  void* p = this->PushBack();
582  if (!p) return nullptr;
583  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1));
584  ++curidx_;
585  return ptr;
586  }
587  template<class A1, class A2>
588  pointer EmplaceBack(const A1& a1, const A2& a2) {
589  void* p = this->PushBack();
590  if (!p) return nullptr;
591  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
592  const_cast<typename RemoveConst<A2>::type&>(a2));
593  ++curidx_;
594  return ptr;
595  }
596  template<class A1, class A2, class A3>
597  pointer EmplaceBack(const A1& a1, const A2& a2, const A3& a3) {
598  void* p = this->PushBack();
599  if (!p) return nullptr;
600  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
601  const_cast<typename RemoveConst<A2>::type&>(a2),
602  const_cast<typename RemoveConst<A3>::type&>(a3));
603  ++curidx_;
604  return ptr;
605  }
606  template<class A1, class A2, class A3, class A4>
607  pointer EmplaceBack(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
608  void* p = this->PushBack();
609  if (!p) return nullptr;
610  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
611  const_cast<typename RemoveConst<A2>::type&>(a2),
612  const_cast<typename RemoveConst<A3>::type&>(a3),
613  const_cast<typename RemoveConst<A4>::type&>(a4));
614  ++curidx_;
615  return ptr;
616  }
617  template<class A1, class A2, class A3, class A4, class A5>
618  pointer EmplaceBack(const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) {
619  void* p = this->PushBack();
620  if (!p) return nullptr;
621  pointer ptr = new (p) T(const_cast<typename RemoveConst<A1>::type&>(a1),
622  const_cast<typename RemoveConst<A2>::type&>(a2),
623  const_cast<typename RemoveConst<A3>::type&>(a3),
624  const_cast<typename RemoveConst<A4>::type&>(a4),
625  const_cast<typename RemoveConst<A5>::type&>(a5));
626  ++curidx_;
627  return ptr;
628  }
629 #endif
631  curblk_ = nullptr;
632  curlevel_ = 0;
633  curidx_ = 0;
634  firstblk_ = nullptr;
635  }
636 
637  private:
638  // The # of elements in the block increases as 8, 16, 32, 64, ....
639  Blk* AllocBlk(size_t n) const NLIB_NOEXCEPT;
640  void DeallocBlkList(Blk* p, int lv) const NLIB_NOEXCEPT;
641  void DestroyBlk(Blk*, size_t, TrueType) const NLIB_NOEXCEPT {}
642  void DestroyBlk(Blk* p, size_t n, FalseType) const NLIB_NOEXCEPT;
643  void DestroyBlk(Blk* p, size_t n) const NLIB_NOEXCEPT {
644  DestroyBlk(p, n, typename IsTriviallyDestructible<T>::type());
645  }
646  bool ConfirmFirstBlk() const NLIB_NOEXCEPT;
647  void* PushBack() NLIB_NOEXCEPT;
648  void Clear(FalseType) NLIB_NOEXCEPT;
649  void Clear(TrueType) NLIB_NOEXCEPT { ClearSimple(); }
650  bool Resize(size_t n, FalseType) NLIB_NOEXCEPT;
651  bool Resize(size_t n, TrueType) NLIB_NOEXCEPT;
652  T* MyCtor(void* p, TrueType) NLIB_NOEXCEPT {
653  nlib_memset(p, 0, sizeof(T));
654  return static_cast<T*>(p);
655  }
656  T* MyCtor(void* p, FalseType) {
657  T* ptr = new (p) T; // may throw
658  return ptr;
659  }
660  bool pop_back_(FalseType) NLIB_NOEXCEPT {
661  if (curidx_ == 0) {
662  if (!ConfirmBack()) return false;
663  }
664  reference item = GetItem(curblk_)[--curidx_];
665  NLIB_UNUSED(item);
666  item.~T();
667  return true;
668  }
669  bool pop_back_(TrueType) NLIB_NOEXCEPT {
670  if (curidx_ == 0) {
671  if (!ConfirmBack()) return false;
672  }
673  --curidx_;
674  return true;
675  }
676 
677  private:
679 };
680 
681 template<class T, class AL>
683  this->clear();
684  this->DeallocBlkList(firstblk_, 0);
685 }
686 
687 namespace nlist {
688 
689 template<class T, class AL>
690 class ResizeRewinder {
691  public:
692  ResizeRewinder(Nlist<T, AL>& l) NLIB_NOEXCEPT : count_(0), list_(l) {}
693  void PushBack(size_t n) {
694  for (; count_ < n; ++count_) {
695  list_.push_back(); // may throw in the default constructor of T
696  }
697  count_ = 0;
698  }
699  ~ResizeRewinder() NLIB_NOEXCEPT {
700  for (; count_ > 0; --count_) {
701  list_.pop_back();
702  }
703  }
704 
705  private:
706  size_t count_;
707  Nlist<T, AL>& list_;
708  NLIB_DISALLOW_COPY_AND_ASSIGN(ResizeRewinder);
709 };
710 
711 } // namespace nlist
712 
713 template<class T, class AL>
714 bool Nlist<T, AL>::Resize(size_t n, FalseType) NLIB_NOEXCEPT {
715  // NOTE: This can be optimized.
716  size_t sz = this->size();
717  if (n == sz) return true;
718  if (n < sz) {
719  for (size_t i = sz; i > n; --i) {
720  this->pop_back();
721  }
722  } else {
723  if (!this->reserve(n)) return false;
724  nlist::ResizeRewinder<T, AL> rewinder(*this);
725  rewinder.PushBack(n);
726  }
727  return true;
728 }
729 
730 template<class T, class AL>
731 bool Nlist<T, AL>::Resize(size_t n, TrueType) NLIB_NOEXCEPT {
732  size_type sz = this->size();
733  if (n == sz) return true;
734  if (n < sz) {
735  for (size_type i = sz; i > n; --i) {
736  this->pop_back();
737  }
738  } else {
739  if (!this->reserve(n)) return false;
740  // NOTE:
741  // Just set curlevel_, curblk_, curidx_
742  // because we don't have to invoke the constuctor of T.
743  size_t lower = this->BlkBaseIdx(curlevel_);
744  size_t upper = this->BlkBaseIdx(curlevel_ + 1);
745  while (upper <= n) {
746  size_t curmax_idx = BlkSize(curlevel_);
747  void* buf = reinterpret_cast<nlib_byte_t*>(curblk_->item) + curidx_ * sizeof(T);
748  size_t fill_size = (curmax_idx - curidx_) * sizeof(T);
749  nlib_memset(buf, 0, fill_size);
750  ++curlevel_;
751  curidx_ = 0;
752  curblk_ = curblk_->next;
753  lower = upper;
754  upper = this->BlkBaseIdx(curlevel_ + 1);
755  }
756  size_t old_curidx = curidx_;
757  curidx_ = static_cast<size_t>(n - lower);
758  void* buf = reinterpret_cast<nlib_byte_t*>(curblk_->item) + old_curidx * sizeof(T);
759  size_t fill_size = (curidx_ - old_curidx) * sizeof(T);
760  nlib_memset(buf, 0, fill_size);
761  }
762  return true;
763 }
764 
765 template<class T, class AL>
767  if (NLIB_UNLIKELY(n == 0)) return true;
768  if (!firstblk_ && !this->ConfirmFirstBlk()) return false;
769  if (n < BlkBaseIdx(curlevel_ + 1)) return true;
770  size_t lv;
771  Blk* blk = this->LastBlock(&lv);
772  for (;;) {
773  if (n < BlkBaseIdx(lv + 1)) return true;
774  ++lv;
775  Blk* p = this->AllocBlk(BlkSize(lv));
776  if (!p) return false;
777  blk->next = p;
778  blk = p;
779  }
780 }
781 
782 template<class T, class AL>
783 typename Nlist<T, AL>::Blk* Nlist<T, AL>::AllocBlk(size_t n) const NLIB_NOEXCEPT {
784  NLIB_STATIC_ASSERT(NLIB_ALIGNOF(T) == 1 || NLIB_ALIGNOF(T) == 2 || NLIB_ALIGNOF(T) == 4 ||
785  NLIB_ALIGNOF(T) == 8);
786  NLIB_STATIC_ASSERT(sizeof(Blk) % 8 == 0);
787  size_t sz = sizeof(Blk) + n * sizeof(T);
788  void* pp;
789  NLIB_TRY {
790  pp = AllocType::_GetNlistAlloc().allocate(sz); // must be 8 bytes aligned
791  }
792 #ifdef __cpp_exceptions
793  NLIB_CATCH(const std::bad_alloc&) { return nullptr; }
794 #endif
795  if (!pp) return nullptr;
796  Blk* p = static_cast<Blk*>(pp);
797  p->next = nullptr;
798  p->item = reinterpret_cast<T*>(p + 1);
799  return p;
800 }
801 
802 template<class T, class AL>
803 void Nlist<T, AL>::DeallocBlkList(Blk* p, int lv) const NLIB_NOEXCEPT {
804  while (p) {
805  size_t n = BlkSize(lv);
806  Blk* pp = p;
807  p = pp->next;
808 
809  // DeallocBlock
810  AllocType::_GetNlistAlloc().deallocate(reinterpret_cast<char*>(pp),
811  sizeof(Blk) + n * sizeof(T));
812  ++lv;
813  }
814 }
815 
816 template<class T, class AL>
817 void Nlist<T, AL>::DestroyBlk(Blk* p, size_t n, FalseType) const NLIB_NOEXCEPT {
818  // NOTE:
819  // Do not use std::allocator::destroy() because destroy() is not required.
820  // invoke the destructor directly.
821  T* base = static_cast<T*>(p->item);
822  NLIB_UNUSED(base);
823  for (size_t i = 0; i < n; ++i) {
824  (base + i)->~T();
825  }
826 }
827 
828 template<class T, class AL>
829 bool Nlist<T, AL>::ConfirmFirstBlk() const NLIB_NOEXCEPT {
830  Blk* p = AllocBlk(BlkSize(0));
831  if (!p) return false;
832  firstblk_ = p;
833  curblk_ = p;
834  curidx_ = 0;
835  curlevel_ = 0;
836  return true;
837 }
838 
839 template<class T, class AL>
840 void* Nlist<T, AL>::PushBack() NLIB_NOEXCEPT {
841  if (!firstblk_ && !ConfirmFirstBlk()) return nullptr;
842  if (curidx_ == BlkSize(curlevel_)) {
843  if (!curblk_->next) {
844  Blk* p = AllocBlk(BlkSize(curlevel_ + 1));
845  if (!p) return nullptr;
846  curblk_->next = p;
847  }
848  ++curlevel_;
849  curblk_ = curblk_->next;
850  curidx_ = 0;
851  }
852 
853  // NOTE:
854  // If curidx_ is incremented here,
855  // The state will be inconsisitent when T's constructor throws an exception.
856  T& item = GetItem(curblk_)[curidx_];
857  return &item;
858 }
859 
860 template<class T, class AL>
861 void Nlist<T, AL>::Clear(FalseType) NLIB_NOEXCEPT {
862  int lv = 0;
863  Blk* p = firstblk_;
864  if (!p) return;
865  while (p != curblk_) {
866  size_t cnt = BlkSize(lv);
867  DestroyBlk(p, cnt);
868  ++lv;
869  p = p->next;
870  }
871  if (p == curblk_) {
872  DestroyBlk(p, curidx_);
873  }
874  ClearSimple();
875 }
876 
877 template<class T, class AL1, class AL2>
878 inline bool operator==(const Nlist<T, AL1>& lhs, const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
879  return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
880 }
881 
882 template<class T, class AL1, class AL2>
883 inline bool operator!=(const Nlist<T, AL1>& lhs, const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
884  return !(lhs == rhs);
885 }
886 
887 template<class T, class AL1, class AL2>
888 inline bool operator<(const Nlist<T, AL1>& lhs, const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
889  return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
890 }
891 
892 template<class T, class AL1, class AL2>
893 inline bool operator>(const Nlist<T, AL1>& lhs, const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
894  return (rhs < lhs);
895 }
896 
897 template<class T, class AL1, class AL2>
898 inline bool operator<=(const Nlist<T, AL1>& lhs, const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
899  return (!(rhs < lhs));
900 }
901 
902 template<class T, class AL1, class AL2>
903 inline bool operator>=(const Nlist<T, AL1>& lhs, const Nlist<T, AL2>& rhs) NLIB_NOEXCEPT {
904  return (!(lhs < rhs));
905 }
906 
907 template<class AL = std::allocator<char> >
908 class StringList {
909  typedef Nlist<char*, AL> ContainerType;
910 
911  public:
912  typedef AL allocator_type;
913  typedef typename ContainerType::iterator iterator;
914  typedef typename ContainerType::const_iterator const_iterator;
915 
916  public:
917  ~StringList() NLIB_NOEXCEPT;
918  size_t size() const NLIB_NOEXCEPT { return list_.size(); }
919  size_t capacity() const NLIB_NOEXCEPT { return list_.capacity(); }
920  bool empty() const NLIB_NOEXCEPT { return list_.empty(); }
921  bool reserve(size_t n) { return list_.reserve(n); }
922  bool resize(size_t n) { return list_.resize(n); }
923 
924  char** push_back(const char* str);
925  template<class Iterator>
926  char** push_back(Iterator first, Iterator last);
927 
928  bool pop_back() NLIB_NOEXCEPT;
929  void clear() NLIB_NOEXCEPT { list_.clear(); }
930  allocator_type get_allocator() const { return list_.get_allocator(); }
931 
932  const char* back() const { return list_.back(); }
933  char* back() { return list_.back(); }
934  const char* front() const { return list_.front(); }
935  char* front() { return list_.front(); }
936  const char* operator[](size_t idx) const { return list_[idx]; }
937  char* operator[](size_t idx) { return list_[idx]; }
938  iterator begin() NLIB_NOEXCEPT { return list_.begin(); }
939  const_iterator begin() const NLIB_NOEXCEPT { return list_.begin(); }
940  const_iterator cbegin() NLIB_NOEXCEPT { return list_.cbegin(); }
941 
942  iterator end() NLIB_NOEXCEPT { return list_.end(); }
943  const_iterator end() const NLIB_NOEXCEPT { return list_.end(); }
944  const_iterator cend() NLIB_NOEXCEPT { return list_.cend(); }
945 
946  void shrink_to_fit() { list_.shrink_to_fit(); }
947  void Clobber() NLIB_NOEXCEPT { list_.clobber(); }
948 
949  char** Replace(iterator it, const char* str);
950  char** Replace(size_t idx, const char* str) {
951  if (idx >= list_.size()) return nullptr;
952  iterator it = list_.begin();
953  it.Advance(idx);
954  return this->Replace(it, str);
955  }
956 
957  private:
958  void Dealloc(const char* ptr) const {
959  if (ptr) {
960  // NOTE: note that size info is not supplied.
961  this->get_allocator().deallocate(const_cast<char*>(ptr), 0);
962  }
963  }
964  char* StrDup(const char* ptr) const;
965  char* Alloc(size_t nbytes) const { return this->get_allocator().allocate(nbytes); }
966 
967  private:
968  ContainerType list_;
969  NLIB_DISALLOW_COPY_AND_ASSIGN(StringList);
970 };
971 
972 template<class AL>
973 char* StringList<AL>::StrDup(const char* ptr) const {
974  size_t nbytes = nlib_strlen(ptr) + 1;
975  void* p = this->Alloc(nbytes);
976  if (!p) return nullptr;
977  nlib_memcpy(p, nbytes, ptr, nbytes);
978  return reinterpret_cast<char*>(p);
979 }
980 
981 template<class AL>
982 StringList<AL>::~StringList() NLIB_NOEXCEPT {
983  const_iterator it = this->cbegin();
984  const_iterator it_end = this->cend();
985  while (it != it_end) {
986  Dealloc(*it);
987  ++it;
988  }
989 }
990 
991 template<class AL>
992 char** StringList<AL>::push_back(const char* str) {
993  char* dup;
994  if (str) {
995  dup = this->StrDup(str);
996  if (!dup) return nullptr;
997  } else {
998  dup = nullptr;
999  }
1000  char** ptr_str = list_.push_back(dup);
1001  if (!ptr_str) this->Dealloc(dup);
1002  return ptr_str;
1003 }
1004 
1005 template<class AL>
1006 template<class Iterator>
1007 char** StringList<AL>::push_back(Iterator first, Iterator last) {
1008  typename std::iterator_traits<Iterator>::difference_type n = std::distance(first, last);
1009  char* str = this->Alloc(n + 1);
1010  if (!str) return nullptr;
1011  std::copy(first, last, str);
1012  str[n] = '\0';
1013  char** rval = list_.push_back(str);
1014  if (!rval) this->Dealloc(str);
1015  return rval;
1016 }
1017 
1018 template<class AL>
1019 bool StringList<AL>::pop_back() NLIB_NOEXCEPT {
1020  if (list_.empty()) return false;
1021  Dealloc(list_.back());
1022  return list_.pop_back();
1023 }
1024 
1025 template<class AL>
1026 char** StringList<AL>::Replace(iterator it, const char* str) {
1027  char* dup;
1028  if (str) {
1029  dup = this->StrDup(str);
1030  if (!dup) return nullptr;
1031  } else {
1032  dup = nullptr;
1033  }
1034  Dealloc(*it);
1035  *it = dup;
1036  return &*it;
1037 }
1038 
1039 template<class AL>
1040 bool AppendString(Nlist<char, AL>* obj, const char* str) {
1041  size_t n = nlib_strlen(str);
1042  if (!obj->reserve(obj->size() + n)) return false;
1043  while (*str) {
1044  obj->push_back(*str);
1045  ++str;
1046  }
1047  return true;
1048 }
1049 
1050 NLIB_NAMESPACE_END
1051 
1052 namespace std {
1053 
1054 template<class T, class Distance>
1055 inline void advance(::nlib_ns::nlist::NlistIterator<T>& pos, Distance n) {
1056  pos.Advance(static_cast<size_t>(n));
1057 }
1058 
1059 template<class T>
1060 inline std::ptrdiff_t distance(const ::nlib_ns::nlist::NlistIterator<T>& first,
1061  const ::nlib_ns::nlist::NlistIterator<T>& last) {
1062  return first.Distance(last);
1063 }
1064 
1065 } // namespace std
1066 
1067 NLIB_DEFINE_STD_SWAP_T_BEGIN2(nn, nlib)
1068 NLIB_DEFINE_STD_SWAP_T2(T, AL, NLIB_NS::Nlist)
1069 NLIB_DEFINE_STD_SWAP_T1(AL, NLIB_NS::StringList)
1070 NLIB_DEFINE_STD_SWAP_T_END2(nn, nlib)
1071 
1072 #endif // INCLUDE_NN_NLIB_NLIST_H_
Nlist(const AL &al) noexcept
アロケータを指定します。空のコンテナを作成します。
Definition: Nlist.h:440
reference operator[](size_type n)
n番目の要素を取得します。nは格納されている要素数未満である必要があります。
Definition: Nlist.h:529
BaseType::const_pointer const_pointer
要素への読み取り専用ポインタです。
Definition: Nlist.h:434
pointer EmplaceBack(Args &&... args)
インプレイスで要素を追加します。
Definition: Nlist.h:571
static errno_t nlib_memset(void *buf, int ch, size_t n)
内部でmemset(buf, ch, n)相当の関数を呼び出します。
Definition: Platform.h:2544
reference back()
最後の要素への参照を取得します。
Definition: Nlist.h:511
BaseType::pointer pointer
要素へのポインタです。
Definition: Nlist.h:433
C++11の標準ヘッダとなるtype_traitsの代用定義です。 コンパイラや標準ライブラリによってサポートされてい...
Nlist() noexcept
デフォルトコンストラクタです。 空のコンテナを作成します。
Definition: Nlist.h:439
BaseType::reference reference
要素への参照です。
Definition: Nlist.h:431
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
Definition: Config.h:183
bool operator>=(const Nlist< T, AL1 > &lhs, const Nlist< T, AL2 > &rhs) noexcept
2つのリストを辞書順で比較します。
Definition: Nlist.h:903
const_iterator begin() const noexcept
先頭要素を指す読み取り専用反復子を取得します。
Definition: Nlist.h:541
Definition: Base64.h:25
BaseType::size_type size_type
符号なし整数型(size_t)
Definition: Nlist.h:429
bool operator>(const Nlist< T, AL1 > &lhs, const Nlist< T, AL2 > &rhs) noexcept
2つのリストを辞書順で比較します。
Definition: Nlist.h:893
iterator begin() noexcept
先頭要素を指す反復子を取得します。
Definition: Nlist.h:537
STL namespace
void shrink_to_fit() noexcept
可能ならばアロケートされたメモリを返却します。
Definition: Nlist.h:563
allocator_type get_allocator() const noexcept
アロケータを取得します。
Definition: Nlist.h:509
const_reference back() const
上記関数のconst修飾付き版です。
Definition: Nlist.h:516
#define NLIB_UNLIKELY(x)
条件xが偽になる傾向が高いことをコンパイラに示します。
Definition: Platform_unix.h:98
const_iterator end() const noexcept
末尾の次を指す読み取り専用反復子を取得します。
Definition: Nlist.h:554
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価ならば、trueを返します。
Definition: NMalloc.h:130
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価でなければ、trueを返します。
Definition: NMalloc.h:135
pointer push_back(T &&rhs) noexcept
一時オブジェクトrhsをムーブして末尾に追加します。
Definition: Nlist.h:483
BaseType::const_iterator const_iterator
読み取り専用前方反復子です。
Definition: Nlist.h:436
#define NLIB_VIS_PUBLIC
関数やクラス等のシンボルをライブラリの外部に公開します。
Definition: Platform_unix.h:87
Nlist & operator=(Nlist &&rhs) noexcept
ムーブ代入演算子です。
Definition: Nlist.h:448
MessagePack又はJSONを読み込むことで作成されるオブジェクトです。
Definition: MpObject.h:96
size_type capacity() const noexcept
アロケート済みの要素の個数を返します。
Definition: Nlist.h:466
bool resize(size_type n) noexcept
コンテナをリサイズします。
Definition: Nlist.h:471
pointer push_back()
末尾に要素を追加してデフォルトコンストラクタで初期化します。
Definition: Nlist.h:475
Nlist(Nlist &rhs, move_tag) noexcept
ムーブコンストラクタに相当します。
Definition: Nlist.h:456
空の構造体で、関数の引数をムーブすべきことを示すために利用されます。
Definition: Config.h:270
void clear() noexcept
コンテナをクリアします。
Definition: Nlist.h:508
#define NLIB_CATCH(x)
例外が有効なときはcatch(x), そうでなければif (true)が定義されます。
Definition: Config.h:147
#define NLIB_TRY
例外が有効なときはtry, そうでなければif (true)が定義されます。
Definition: Config.h:146
Nlist & assign(Nlist &rhs, move_tag) noexcept
ムーブ代入演算子に相当します。
Definition: Nlist.h:458
reference front()
最初の要素への参照を取得します。
Definition: Nlist.h:521
BaseType::iterator iterator
前方反復子です。
Definition: Nlist.h:435
const_reference operator[](size_type n) const
上記関数のconst修飾付き版です。
Definition: Nlist.h:533
BaseType::difference_type difference_type
符号つき整数型(ptrdiff_t)
Definition: Nlist.h:430
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:109
BaseType::value_type value_type
要素型 T
Definition: Nlist.h:427
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:111
開発環境別の設定が書かれるファイルです。
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
rhs を i 倍します。
Definition: DateTime.h:195
pointer push_back(const T &rhs)
rhsを末尾に追加します。
Definition: Nlist.h:498
void Clobber() noexcept
要素のデストラクタを呼んだりコンテナのメモリを解放することなく、コンテナを空に戻す。 ...
Definition: Nlist.h:630
std::vectorに似た、コピーコンストラクタを持たないオブジェクトを格納可能なコンテナ類似クラスです。 ...
Definition: Nlist.h:32
const_reference front() const
上記関数のconst修飾付き版です。
Definition: Nlist.h:525
const_iterator cend() const noexcept
末尾の次を指す読み取り専用反復子を取得します。
Definition: Nlist.h:558
size_type size() const noexcept
格納されている要素数を返します。
Definition: Nlist.h:465
size_t nlib_strlen(const char *s)
内部でstrlen()を呼び出します。独自の実装が動作する場合もあります。
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
Definition: Config.h:250
#define NLIB_STATIC_ASSERT(exp)
静的アサートが定義されます。利用可能であればstatic_assertを利用します。
Definition: Config.h:174
bool empty() const noexcept
格納されている要素数が0ならばtrue、それ以外ならfalseを返します。
Definition: Nlist.h:470
unsigned char nlib_byte_t
C++17以降でstd::byteにtypedefされる型です。
Definition: Platform.h:314
#define NLIB_ALIGNOF(tp)
alignof(tp)又は同等の定義がされます。
Definition: Config.h:261
AL allocator_type
アロケータの型 AL
Definition: Nlist.h:428
BaseType::reference const_reference
要素への読み取り専用参照です。
Definition: Nlist.h:432
const_iterator cbegin() const noexcept
先頭要素を指す読み取り専用反復子を取得します。
Definition: Nlist.h:545
iterator end() noexcept
末尾の次を指す反復子を取得します。
Definition: Nlist.h:550
bool pop_back() noexcept
末尾の要素を削除します。
Definition: Nlist.h:505