1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ut_MoveArray.h
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: 31777 $
16 *---------------------------------------------------------------------------*/
17
18 #ifndef NW_UT_MOVEARRAY_H_
19 #define NW_UT_MOVEARRAY_H_
20
21 #include <nw/ut/ut_Config.h>
22
23 #include <nw/ut/ut_Preprocessor.h>
24 #include <nw/ut/ut_TypeTraits.h>
25 #include <nw/ut/ut_Flag.h>
26 #include <nw/os/os_Memory.h>
27
28 #include <iterator>
29 #include <algorithm>
30
31 namespace nw
32 {
33
34 namespace ut
35 {
36
37 namespace detail
38 {
39
40 template<typename From, typename To>
41 struct is_convertible
42 {
43 static char test(To*);
44 static int test(...);
45 static const bool value = sizeof( test( static_cast<From*>(NULL) ) ) == 1;
46 };
47
48 }
49
50 //---------------------------------------------------------------------------
51 //! @brief 配列の種類です。
52 //---------------------------------------------------------------------------
53 enum ArrayKind
54 {
55 ARRAY_WRAPPER, //!< 配列をラップするだけの、サイズ変更できない種類です。
56 #ifdef NW_MOVE_ARRAY_VARIABILITY_ENABLED
57 ARRAY_VARIABILITY, //!< ヒープからメモリを確保し、サイズ変更できる種類です。
58 #endif
59 ARRAY_FIXED, //!< ヒープからメモリ確保しない、サイズ変更できない種類です。
60
61 NW_FLAG_VALUE_DECLARE(ARRAY_KIND, 30, 2)
62 };
63
64 //---------------------------------------------------------------------------
65 //! @brief 配列をラッピングして、STL の vector のように使用できるクラスです。
66 //!
67 //! 配列を安全に使用することを目的としています。
68 //! このクラスはムーブセマンティクスを実現するような
69 //! 実装になっており、コピーや代入が特殊な実装になっています。
70 //! 管理するリソースをコピーせず、所有権を移動します。
71 //!
72 //! 生成時に、以下の3つのいずれかの動作方式になります。
73 //!
74 //! 1. サイズを変更できない固定長配列@n
75 //! 2. push_back 時などに自動でサイズ拡張する可変長配列@n
76 //! 3. 配列を持たない無効な状態@n
77 //!
78 //! 所有権の移動元のインスタンスは、移動後に上記の 3 の状態になっています。
79 //! デフォルトコンストラクタで生成したインスタンスも 3 の状態になっています。
80 //! この状態のインスタンスを if の条件文して記述すると false が返るようになっています。
81 //! 1 または 2 の状態では、条件文に記述すると true が返るようになっています。
82 //!
83 //! "nw/ut/ut_Config.h"の"NW_MOVE_ARRAY_VARIABILITY_ENABLED"の定義を無効にして
84 //! ライブラリをビルドしなおすことで、上記 2 の機能を無効化することができます。
85 //!
86 //! @tparam TElement 配列要素の型です。
87 //!
88 //! @sa nw::ut::ArrayKind
89 //---------------------------------------------------------------------------
90 template<typename TElement>
91 class MoveArray
92 {
93 NW_STATIC_ASSERT(!IsArray<TElement>::value);
94
95 public:
96 #ifdef NW_MOVE_ARRAY_CACHE_LINE_ALIGNMENT_ENABLED
97 static const size_t MEMORY_ALIGNMENT = os::IAllocator::CACHE_LINE_ALIGNMENT;
98 #endif
99
100 typedef TElement& reference; //!< 要素の参照です。
101 typedef TElement difference_type; //!< 要素の差です。
102 typedef TElement value_type; //!< 要素の型です。
103 typedef TElement* iterator; //!< 要素のイテレータの型です。
104 typedef const TElement* const_iterator; //!< 要素の const イテレータの型です。
105
106 #if defined(_MSC_VER) && _MSC_VER <= 1201
107 typedef std::reverse_iterator<iterator, TElement> reverse_iterator; //!< 要素のリバースイテレータの型です。
108 typedef std::reverse_iterator<const_iterator, TElement> const_reverse_iterator; //!< 要素の const リバースイテレータの型です。
109 #else
110 typedef std::reverse_iterator<iterator> reverse_iterator; //!< 要素のリバースイテレータの型です。
111 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; //!< 要素の const リバースイテレータの型です。
112 #endif
113
114 public:
115 //! @brief コンストラクタです。
116 //!
117 //! デフォルトコンストラクタです。
118 //! サイズ0の固定長配列として動作します。
119 //! このコンストラクタで作ったインスタンスを if 文等の条件に入れると false が
120 //! 返ります。
121 //!
MoveArray()122 MoveArray()
123 : m_Allocator(NULL),
124 m_Elements(NULL),
125 m_End(NULL)
126 {
127 SetCapacity(0);
128 SetArrayKind(ARRAY_WRAPPER);
129 }
130
131 //! @brief コンストラクタです。
132 //!
133 //! 渡されたメモリをデストラクタで開放してくれるコンストラクタです。
134 //! kind を ARRAY_VARIABILITY にすると、サイズを自動拡張する機能が ON になります。
135 //! サイズが自動拡張されるときには内部でメモリを確保します。
136 //! 内部でメモリを確保するのが適切ではない場合、kind は ARRAY_WRAPPER にしてください。
137 //! また、allocator を 0 にすると、デストラクタでメモリを解放しません。
138 //!
139 //! @param[in] elements 要素格納用に確保されたメモリです。
140 //! @param[in] capacity キャパシティ要素数です。
141 //! @param[in] allocator アロケータです。
142 //! @param[in] kind メモリ拡張方法の種類です。
143 //!
144 template <typename TTElemet>
145 MoveArray(
146 TTElemet* elements,
147 size_t capacity,
148 os::IAllocator* allocator = NULL,
149 ArrayKind kind = ARRAY_WRAPPER
150 )
m_Allocator(allocator)151 : m_Allocator(allocator),
152 m_Elements(reinterpret_cast<TElement*>(elements)),
153 m_End(reinterpret_cast<TElement*>(elements))
154 {
155 // 引数の順番を間違いやすかったので、最初の引数に os::IAllocator 型のポインタ
156 // を渡している場合は、コンパイル時にアサートになるようにしました。
157 NW_STATIC_ASSERT((!detail::is_convertible<TTElemet, os::IAllocator>::value));
158 SetCapacity(capacity);
159 SetArrayKind(kind);
160 }
161
162 //! @brief コンストラクタです。
163 //!
164 //! 指定したサイズのメモリをアロケータから確保してくれるコンストラクタです。
165 //! kind を ARRAY_VARIABILITY にすると、サイズを自動拡張する機能が ON になります。
166 //! サイズが自動拡張されるときには内部でメモリを確保します。
167 //! 内部でメモリを確保するのが適切ではない場合、kind は ARRAY_WRAPPER にしてください。
168 //!
169 //! @param[in] capacity キャパシティ要素数です。
170 //! @param[in] allocator アロケータです。
171 //! @param[in] kind メモリ拡張方法の種類です。
172 //!
173 MoveArray(
174 size_t capacity,
175 os::IAllocator* allocator,
176 ArrayKind kind = ARRAY_WRAPPER
177 )
m_Allocator(allocator)178 : m_Allocator(allocator)
179 {
180 NW_NULL_ASSERT(allocator);
181 if (0 < capacity)
182 {
183 #ifdef NW_MOVE_ARRAY_CACHE_LINE_ALIGNMENT_ENABLED
184 m_Elements = static_cast<TElement*>(allocator->Alloc(sizeof(TElement) * capacity, MEMORY_ALIGNMENT));
185 #else
186 m_Elements = static_cast<TElement*>(allocator->Alloc(sizeof(TElement) * capacity));
187 #endif
188 NW_NULL_ASSERT(m_Elements);
189 }
190 else
191 {
192 m_Elements = NULL;
193 }
194 m_End = m_Elements;
195 SetCapacity(capacity);
196 SetArrayKind(kind);
197 }
198
199 //! @brief コンストラクタです。
200 //!
201 //! メモリのサイズを自動拡張する MoveArray のコンストラクタです。
202 //! サイズが自動拡張されるときには内部でメモリを確保します。
203 //!
204 //! @param[in] allocator アロケータです。
205 //!
MoveArray(os::IAllocator * allocator)206 MoveArray(os::IAllocator* allocator)
207 : m_Allocator(allocator),
208 m_Elements(NULL),
209 m_End(NULL)
210 {
211 NW_NULL_ASSERT(allocator);
212 SetCapacity(0);
213 #ifdef NW_MOVE_ARRAY_VARIABILITY_ENABLED
214 SetArrayKind(ARRAY_VARIABILITY);
215 #endif
216 }
217
218 //! @brief コピー元から要素を移動します。
219 //!
220 //! @param[in] array コピー元の MoveArray オブジェクトです。
221 //!
MoveArray(const MoveArray & array)222 MoveArray(const MoveArray& array)
223 : m_Allocator(array.m_Allocator),
224 m_Elements(array.m_Elements),
225 m_End(array.m_End),
226 m_Capacity(array.m_Capacity)
227 {
228 const_cast<MoveArray&>(array).release();
229 }
230
231 //! @brief デストラクタです。
~MoveArray()232 ~MoveArray()
233 {
234 clear();
235
236 if (m_Allocator && m_Elements)
237 {
238 m_Allocator->Free(m_Elements);
239 }
240 }
241
242 public:
243 //! @details :private
244 struct SafeBoolHelper { int x; };
245 typedef int SafeBoolHelper::* SafeBool; //!< @details :private
246
247 //! @brief 有効な配列を所有する場合に true を返します。
248 //!
249 //! 望まない式評価を行われないような安全な真偽評価を行います。
SafeBool()250 operator SafeBool() const
251 {
252 #ifdef NW_MOVE_ARRAY_VARIABILITY_ENABLED
253 return (capacity() == 0 && GetArrayKind() != ARRAY_VARIABILITY)
254 #else
255 return (capacity() == 0)
256 #endif
257 ? 0
258 : &SafeBoolHelper::x;
259 }
260
261 //! @brief 代入演算子の定義です。
262 MoveArray& operator=(MoveArray rhs)
263 {
264 rhs.swap(*this);
265 return *this;
266 }
267
268 //! @brief 配列の読み取り専用外部公開用アクセッサです。
Elements()269 const TElement* Elements() const { return m_Elements; }
270
271 //! @brief 添え字演算子の定義です。
272 TElement& operator[](int index)
273 {
274 NW_MINMAXLT_ASSERT(index, 0, size());
275 return m_Elements[index];
276 }
277
278 //! @brief 添え字演算子の定義です。
279 const TElement& operator[](int index) const
280 {
281 NW_MINMAXLT_ASSERT(index, 0, size());
282 return m_Elements[index];
283 }
284
285 //! @brief 内部の配列メモリの所有権を手放します。
release()286 TElement* release()
287 {
288 NW_ASSERT(GetArrayKind() != ARRAY_FIXED);
289 TElement* result = m_Elements;
290 m_Elements = 0;
291 m_End = 0;
292 SetCapacity(0);
293 return result;
294 }
295
296 //! @brief MoveArray の管理する配列を再設定します。
297 //!
298 //! 渡されたメモリはデストラクタで開放されます。
299 //! kind を ARRAY_VARIABILITY にすると、サイズを自動拡張する機能が ON になります。
300 //! サイズが自動拡張されるときには内部でメモリを確保します。
301 //! 内部でメモリを確保するのが適切ではない場合、kind は ARRAY_WRAPPER にしてください。
302 //! また、allocator を 0 にすると、デストラクタでメモリを解放しません。
303 //!
304 //! 再設定以前に管理していたメモリはデストラクタが呼ばれ、
305 //! 設定時にアロケータが渡されていればメモリの解放も行います。
306 //!
307 //! @param[in] elements 要素格納用に確保されたメモリです。
308 //! @param[in] size 要素数です。
309 //! @param[in] allocator アロケータです。
310 //! @param[in] kind メモリ拡張方法の種類です。
311 void Reset(
312 void* elements,
313 size_t size,
314 os::IAllocator* allocator = NULL,
315 ArrayKind kind = ARRAY_WRAPPER
316 )
317 {
318 clear();
319
320 if (m_Allocator && m_Elements)
321 {
322 m_Allocator->Free(m_Elements);
323 }
324
325 release();
326
327 m_Allocator = allocator;
328 m_Elements = static_cast<TElement*>(elements);
329 m_End = static_cast<TElement*>(elements);
330
331 SetCapacity(size);
332 SetArrayKind(kind);
333 }
334
335 //! @brief 配列のサイズを取得します。
size()336 int size() const { return m_End - m_Elements; }
337
338 //! @brief 先頭要素へのイテレータを取得します。
begin()339 iterator begin() { return m_Elements; }
340
341 //! @brief 先頭要素へのイテレータを取得します。
begin()342 const_iterator begin() const { return m_Elements; }
343
344 //! @brief 最後尾要素へのイテレータを取得します。
end()345 iterator end() { return m_End; }
346
347 //! @brief 最後尾要素へのイテレータを取得します。
end()348 const_iterator end() const { return m_End; }
349
350 //! @brief 先頭要素へのリバースイテレータを取得します。
rbegin()351 reverse_iterator rbegin() { return reverse_iterator(end()); }
352
353 //! @brief 先頭要素へのリバースイテレータを取得します。
rbegin()354 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
355
356 //! @brief 最後尾要素へのリバースイテレータを取得します。
rend()357 reverse_iterator rend() { return reverse_iterator(begin()); }
358
359 //! @brief 最後尾要素へのリバースイテレータを取得します。
rend()360 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
361
362 //! @brief 先頭要素の参照を取得します。
front()363 TElement& front() { return *m_Elements; }
364
365 //! @brief 先頭要素の参照を取得します。
front()366 const TElement& front() const { return *m_Elements; }
367
368 //! @brief 最後尾要素の参照を取得します。
back()369 TElement& back() { return *(m_End - 1); }
370
371 //! @brief 最後尾要素の参照を取得します。
back()372 const TElement& back() const { return *(m_End - 1); }
373
374 //! @brief 要素が一つもないかのフラグを取得します。確保メモリがないという意味ではありません。
empty()375 bool empty() const { return m_Elements == m_End; }
376
377 //! @brief 確保されているメモリの要素数を取得します。
capacity()378 int capacity() const { return GetCapacity(); }
379
380 //! @brief 配列をコピーします。
CopyFrom(const MoveArray<TElement> & source)381 void CopyFrom(const MoveArray<TElement>& source)
382 {
383 clear();
384
385 NW_MAX_ASSERT(source.size(), GetCapacity());
386 this->resize(source.size());
387 std::copy(source.begin(), source.end(),
388 NW_CHECKED_ARRAY_ITERATOR(this->begin(), this->size()));
389 }
390
391 //----------------------------------------
392 //! @name 配列・メモリ操作
393 //@{
394
395 bool reserve(int reserveSize);
396
397 bool push_back(const TElement& element);
398
399 void pop_back();
400
401 bool assign(int size, const TElement& element);
402
403 void swap(MoveArray<TElement>& other);
404
405 bool resize(int number);
406
407 template <typename TIterator>
408 TIterator erase(TIterator first);
409
410 template <typename TIterator>
411 TIterator erase(TIterator first, TIterator last);
412
413 //! @brief 全ての要素のデストラクタを呼び、要素数を0にします。確保メモリの開放はしません。
clear()414 void clear() { erase(begin()); }
415
416 //! @brief 引数と同じ値の要素を検索し、削除します。
erase_find(const TElement & element)417 bool erase_find(const TElement& element)
418 {
419 iterator removed = std::remove(begin(), end(), element);
420 bool IsErased = removed != end();
421 erase(removed);
422 return IsErased;
423 }
424
425 //! @brief 条件に当てはまる要素を検索し、削除します。
426 template<typename Predicate>
erase_if(Predicate predicate)427 bool erase_if(Predicate predicate)
428 {
429 iterator removed = std::remove_if(begin(), end(), predicate);
430 bool IsErased = removed != end();
431 erase(removed);
432 return IsErased;
433 }
434
435 //! @brief 現在の要素数に合わせて予約メモリを縮めます。
436 //!
437 //! GetArrayKind() が ARRAY_VARIABILITY の時だけに働きます。
438 //!
ShrinkToFit()439 void ShrinkToFit()
440 {
441 #ifdef NW_MOVE_ARRAY_VARIABILITY_ENABLED
442 if (GetArrayKind() == ARRAY_VARIABILITY)
443 {
444 MoveArray clone(size(), m_Allocator, GetArrayKind());
445 clone.CopyFrom(*this);
446 clone.swap(*this);
447 }
448 #endif
449 }
450
451 //! @brief メモリ確保についての種類を取得します。
GetArrayKind()452 ArrayKind GetArrayKind() const
453 {
454 return GetFlagValue<ArrayKind>(
455 m_Capacity, FLAG_ARRAY_KIND_VALUE_SHIFT, FLAG_ARRAY_KIND_VALUE_MASK);
456 }
457
458 //! @brief アロケータを取得します。
GetAllocator()459 os::IAllocator& GetAllocator() { return *m_Allocator; }
460
461 //@}
462
463 protected:
464 os::IAllocator* m_Allocator;
465 TElement* m_Elements;
466 TElement* m_End;
467
468 //! @brief 配列の種類を設定します。
SetArrayKind(ArrayKind kind)469 void SetArrayKind(ArrayKind kind)
470 {
471 m_Capacity =
472 SetFlagValue(m_Capacity, FLAG_ARRAY_KIND_VALUE_SHIFT, FLAG_ARRAY_KIND_VALUE_MASK, kind);
473 }
474
475 //! @brief 確保数を設定します。
SetCapacity(int capacity)476 void SetCapacity(int capacity)
477 {
478 // HACK: コンパイラを黙らせる static_cast<> を仮挿入。
479 m_Capacity = (m_Capacity & static_cast<size_t>(FLAG_ARRAY_KIND_VALUE_MASK)) | static_cast<size_t>(capacity);
480 }
481
482 //! @brief 確保数を取得します。
GetCapacity()483 int GetCapacity() const
484 {
485 return m_Capacity & (~FLAG_ARRAY_KIND_VALUE_MASK);
486 }
487
488 private:
489 // m_Capacity は直接参照しないでください。必ず SetCapacity(), GetCapacity() を使用してください。
490 size_t m_Capacity;
491
492 //! 割当て済みの領域にコンストラクタを呼び出します。
construct(TElement * element,const TElement & value)493 void construct(TElement* element, const TElement& value)
494 {
495 new(static_cast<void*>(element)) TElement(value);
496 }
497 //! 割当て済みの領域にコンストラクタを呼び出します。
construct(TElement * element)498 void construct(TElement* element)
499 {
500 new(static_cast<void*>(element)) TElement();
501 }
502 //! 初期化済みの領域のデストラクタを呼び出します。
destroy(TElement * element)503 void destroy(TElement* element)
504 {
505 NW_UNUSED_VARIABLE(element); // プリミティブ型での警告を回避するため
506 element->~TElement();
507 }
508 //! 要素を移動するためにコンストラクタを呼び出します。
move_construct(iterator dest,const TElement & source)509 void move_construct(iterator dest, const TElement& source)
510 {
511 new(static_cast<void*>(dest)) TElement(source);
512 }
513 //! 初期化済みの領域のデストラクタをまとめて呼び出します。
destroy_range(iterator first,iterator last)514 void destroy_range(iterator first, iterator last)
515 {
516 if (IsClass<TElement>::value)
517 {
518 for (; first != last; ++first)
519 {
520 destroy(first);
521 }
522 }
523 }
524
525 public:
526 //----------------------------------------
527 //! @name NintendoWare のコーディングルール準拠のエイリアス。
528 //@{
529
530 //! @brief 配列のサイズを取得します。
Size()531 int Size() const { return this->size(); }
532 //! @brief 先頭要素へのイテレータを取得します。
Begin()533 iterator Begin() { return this->begin(); }
534 //! @brief 先頭要素へのイテレータを取得します。
Begin()535 const_iterator Begin() const { return this->begin(); }
536 //! @brief 最後尾要素へのイテレータを取得します。
End()537 iterator End() { return this->end(); }
538 //! @brief 最後尾要素へのイテレータを取得します。
End()539 const_iterator End() const { return this->end(); }
540 //! @brief 先頭要素へのリバースイテレータを取得します。
RBegin()541 reverse_iterator RBegin() { return this->rbegin(); }
542 //! @brief 先頭要素へのリバースイテレータを取得します。
RBegin()543 const_reverse_iterator RBegin() const { return this->rbegin(); }
544 //! @brief 最後尾要素へのリバースイテレータを取得します。
REnd()545 reverse_iterator REnd() { return this->rend(); }
546 //! @brief 最後尾要素へのリバースイテレータを取得します。
REnd()547 const_reverse_iterator REnd() const { return this->rend(); }
548 //! @brief 配列のサイズを取得します。
Front()549 TElement& Front() { return this->front(); }
550 //! @brief 先頭要素の参照を取得します。
Front()551 const TElement& Front() const { return this->front(); }
552 //! @brief 最後尾要素の参照を取得します。
Back()553 TElement& Back() { return this->back(); }
554 //! @brief 最後尾要素の参照を取得します。
Back()555 const TElement& Back() const { return this->back(); }
556 //! @brief 要素が一つもないかのフラグを取得します。確保メモリがないという意味ではありません。
Empty()557 bool Empty() const { return this->empty(); }
558 //! @brief 確保されているメモリの要素数を取得します。
Capacity()559 int Capacity() const { return this->capacity(); }
560 //! @brief 指定要素数分のメモリを予約します。
Reserve(int reserveSize)561 bool Reserve(int reserveSize) { return this->reserve( reserveSize ); }
562 //! @brief 末尾に要素を追加します。
PushBack(const TElement & element)563 bool PushBack(const TElement& element) { return this->push_back( element ); }
564 //! @brief 末尾の要素を破棄します。
PopBack()565 void PopBack() { this->pop_back(); }
566 //! @brief 指定数の要素を引数 element で埋めます。
Assign(int size,const TElement & element)567 bool Assign(int size, const TElement& element) { return this->assign(size, element); }
568 //! @brief 配列の内容を入れ替えます。
Swap(MoveArray<TElement> & other)569 void Swap(MoveArray<TElement>& other) { this->swap(other); }
570 //! @brief サイズを変更します。
Resize(int number)571 bool Resize(int number) { return this->resize( number ); }
572 //! @brief 指定したイテレータ以降の要素を削除します。
Erase(TIterator first)573 template <typename TIterator> TIterator Erase(TIterator first) { return this->erase( first ); }
574 //! @brief 指定したイテレータ間の要素を削除します。
Erase(TIterator first,TIterator last)575 template <typename TIterator> TIterator Erase(TIterator first, TIterator last) { return this->erase( first, last ); }
576 //! @brief 全ての要素のデストラクタを呼び、要素数を0にします。確保メモリの開放はしません。
Clear()577 void Clear() { this->clear(); }
578 //! @brief 引数と同じ値の要素を検索し、削除します。
EraseFind(const TElement & element)579 void EraseFind(const TElement& element) { this->erase_find( element ); }
580 //! @brief 条件に当てはまる要素を検索し、削除します。
EraseIf(Predicate predicate)581 template<typename Predicate> void EraseIf(Predicate predicate) { this->erase_if( predicate ); }
582
583 //@}
584
585 //----------------------------------------
586 //! @name 最適化用
587 //@{
588
589 //! @brief 高速版の push_back です。
590 //!
591 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
592 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
593 //!
594 //! @param[in] arg0 配列要素のコンストラクタの引数です。
595 template<typename TArg0>
PushBackFast(TArg0 arg0)596 void PushBackFast(TArg0 arg0)
597 {
598 NW_MAX_ASSERT(size(), GetCapacity());
599 new(m_End++) TElement(arg0);
600 }
601
602 //! @brief 高速版の push_back です。
603 //!
604 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
605 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
606 //!
607 //! @param[in] arg0 配列要素のコンストラクタの引数です。
608 //! @param[in] arg1 配列要素のコンストラクタの引数です。
609 template<typename TArg0, typename TArg1>
PushBackFast(TArg0 arg0,TArg1 arg1)610 void PushBackFast(TArg0 arg0, TArg1 arg1)
611 {
612 NW_MAX_ASSERT(size(), GetCapacity());
613 new(m_End++) TElement(arg0, arg1);
614 }
615
616 //! @brief 高速版の push_back です。
617 //!
618 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
619 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
620 //!
621 //! @param[in] arg0 配列要素のコンストラクタの引数です。
622 //! @param[in] arg1 配列要素のコンストラクタの引数です。
623 //! @param[in] arg2 配列要素のコンストラクタの引数です。
624 template<typename TArg0, typename TArg1, typename TArg2>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2)625 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2)
626 {
627 NW_MAX_ASSERT(size(), GetCapacity());
628 new(m_End++) TElement(arg0, arg1, arg2);
629 }
630
631 //! @brief 高速版の push_back です。
632 //!
633 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
634 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
635 //!
636 //! @param[in] arg0 配列要素のコンストラクタの引数です。
637 //! @param[in] arg1 配列要素のコンストラクタの引数です。
638 //! @param[in] arg2 配列要素のコンストラクタの引数です。
639 //! @param[in] arg3 配列要素のコンストラクタの引数です。
640 template<typename TArg0, typename TArg1, typename TArg2, typename TArg3>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2,TArg3 arg3)641 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3)
642 {
643 NW_MAX_ASSERT(size(), GetCapacity());
644 new(m_End++) TElement(arg0, arg1, arg2, arg3);
645 }
646
647 //! @brief 高速版の push_back です。
648 //!
649 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
650 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
651 //!
652 //! @param[in] arg0 配列要素のコンストラクタの引数です。
653 //! @param[in] arg1 配列要素のコンストラクタの引数です。
654 //! @param[in] arg2 配列要素のコンストラクタの引数です。
655 //! @param[in] arg3 配列要素のコンストラクタの引数です。
656 //! @param[in] arg4 配列要素のコンストラクタの引数です。
657 template<typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2,TArg3 arg3,TArg4 arg4)658 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
659 {
660 NW_MAX_ASSERT(size(), GetCapacity());
661 new(m_End++) TElement(arg0, arg1, arg2, arg3, arg4);
662 }
663
664 //! @brief 高速版の push_back です。
665 //!
666 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
667 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
668 //!
669 //! @param[in] arg0 配列要素のコンストラクタの引数です。
670 //! @param[in] arg1 配列要素のコンストラクタの引数です。
671 //! @param[in] arg2 配列要素のコンストラクタの引数です。
672 //! @param[in] arg3 配列要素のコンストラクタの引数です。
673 //! @param[in] arg4 配列要素のコンストラクタの引数です。
674 //! @param[in] arg5 配列要素のコンストラクタの引数です。
675 template<typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2,TArg3 arg3,TArg4 arg4,TArg5 arg5)676 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5)
677 {
678 NW_MAX_ASSERT(size(), GetCapacity());
679 new(m_End++) TElement(arg0, arg1, arg2, arg3, arg4, arg5);
680 }
681
682 //! @brief 高速版の push_back です。
683 //!
684 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
685 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
686 //!
687 //! @param[in] arg0 配列要素のコンストラクタの引数です。
688 //! @param[in] arg1 配列要素のコンストラクタの引数です。
689 //! @param[in] arg2 配列要素のコンストラクタの引数です。
690 //! @param[in] arg3 配列要素のコンストラクタの引数です。
691 //! @param[in] arg4 配列要素のコンストラクタの引数です。
692 //! @param[in] arg5 配列要素のコンストラクタの引数です。
693 //! @param[in] arg6 配列要素のコンストラクタの引数です。
694 template<typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2,TArg3 arg3,TArg4 arg4,TArg5 arg5,TArg6 arg6)695 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6)
696 {
697 NW_MAX_ASSERT(size(), GetCapacity());
698 new(m_End++) TElement(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
699 }
700
701 //! @brief 高速版の push_back です。
702 //!
703 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
704 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
705 //!
706 //! @param[in] arg0 配列要素のコンストラクタの引数です。
707 //! @param[in] arg1 配列要素のコンストラクタの引数です。
708 //! @param[in] arg2 配列要素のコンストラクタの引数です。
709 //! @param[in] arg3 配列要素のコンストラクタの引数です。
710 //! @param[in] arg4 配列要素のコンストラクタの引数です。
711 //! @param[in] arg5 配列要素のコンストラクタの引数です。
712 //! @param[in] arg6 配列要素のコンストラクタの引数です。
713 //! @param[in] arg7 配列要素のコンストラクタの引数です。
714 template<typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2,TArg3 arg3,TArg4 arg4,TArg5 arg5,TArg6 arg6,TArg7 arg7)715 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7)
716 {
717 NW_MAX_ASSERT(size(), GetCapacity());
718 new(m_End++) TElement(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
719 }
720
721 //! @brief 高速版の push_back です。
722 //!
723 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
724 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
725 //!
726 //! @param[in] arg0 配列要素のコンストラクタの引数です。
727 //! @param[in] arg1 配列要素のコンストラクタの引数です。
728 //! @param[in] arg2 配列要素のコンストラクタの引数です。
729 //! @param[in] arg3 配列要素のコンストラクタの引数です。
730 //! @param[in] arg4 配列要素のコンストラクタの引数です。
731 //! @param[in] arg5 配列要素のコンストラクタの引数です。
732 //! @param[in] arg6 配列要素のコンストラクタの引数です。
733 //! @param[in] arg7 配列要素のコンストラクタの引数です。
734 //! @param[in] arg8 配列要素のコンストラクタの引数です。
735 template<typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2,TArg3 arg3,TArg4 arg4,TArg5 arg5,TArg6 arg6,TArg7 arg7,TArg8 arg8)736 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8)
737 {
738 NW_MAX_ASSERT(size(), GetCapacity());
739 new(m_End++) TElement(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
740 }
741
742 //! @brief 高速版の push_back です。
743 //!
744 //! 範囲チェックは Assert のみ、キャパシティの自動拡張機能は働きません。
745 //! 初期化時など、明示的に reserve して配列要素を生成したいケースなどに利用してください。
746 //!
747 //! @param[in] arg0 配列要素のコンストラクタの引数です。
748 //! @param[in] arg1 配列要素のコンストラクタの引数です。
749 //! @param[in] arg2 配列要素のコンストラクタの引数です。
750 //! @param[in] arg3 配列要素のコンストラクタの引数です。
751 //! @param[in] arg4 配列要素のコンストラクタの引数です。
752 //! @param[in] arg5 配列要素のコンストラクタの引数です。
753 //! @param[in] arg6 配列要素のコンストラクタの引数です。
754 //! @param[in] arg7 配列要素のコンストラクタの引数です。
755 //! @param[in] arg8 配列要素のコンストラクタの引数です。
756 //! @param[in] arg9 配列要素のコンストラクタの引数です。
757 template<typename TArg0, typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5, typename TArg6, typename TArg7, typename TArg8, typename TArg9>
PushBackFast(TArg0 arg0,TArg1 arg1,TArg2 arg2,TArg3 arg3,TArg4 arg4,TArg5 arg5,TArg6 arg6,TArg7 arg7,TArg8 arg8,TArg9 arg9)758 void PushBackFast(TArg0 arg0, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7, TArg8 arg8, TArg9 arg9)
759 {
760 NW_MAX_ASSERT(size(), GetCapacity());
761 new(m_End++) TElement(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
762 }
763
764 //@}
765
766 };
767
768 //---------------------------------------------------------------------------
769 //! @brief 固定長の配列クラスです。内部でヒープメモリの確保は行いません。
770 //!
771 //! @tparam TElement 配列要素の型です。
772 //! @tparam TSize 配列の要素数です。
773 //---------------------------------------------------------------------------
774 template<typename TElement, size_t TSize>
775 class FixedSizeArray : public MoveArray<TElement>
776 {
777 private:
778 NW_DISALLOW_COPY_AND_ASSIGN(FixedSizeArray);
779 NW_STATIC_ASSERT(0 < TSize);
780 public:
781 //! コンストラクタです。
FixedSizeArray()782 FixedSizeArray()
783 : MoveArray<TElement>(reinterpret_cast<TElement*>(m_FixedSizeElements), TSize, 0, ARRAY_FIXED) {}
784
785 private:
786 void swap(MoveArray<TElement>& array);
787 TElement* release();
788
789 u8 m_FixedSizeElements[sizeof(TElement) * TSize] NN_ATTRIBUTE_ALIGN(32);
790 };
791
792 //---------------------------------------------------------------------------
793 //! @brief 指定要素数分のメモリを予約します。
794 //! GetArrayKind() が ARRAY_VARIABILITY の時だけに働きます。
795 //! 要求されたサイズを予約できない場合、返り値に false を返します。
796 //! reserve で予約メモリを縮めることはできません。
797 //! その場合、shrink_to_fit を利用してください。
798 //!
799 //! @tparam TElement 要素の型です。
800 //!
801 //! @param[in] reserveSize 予約領域の容量(キャパシティ)です。
802 //!
803 //! @return 予約領域を拡張できなかった場合に false が返ります。
804 //---------------------------------------------------------------------------
805 template<typename TElement>
806 NW_INLINE bool
reserve(int reserveSize)807 MoveArray<TElement>::reserve(int reserveSize)
808 {
809 #ifdef NW_MOVE_ARRAY_VARIABILITY_ENABLED
810 if (reserveSize <= capacity())
811 {
812 return true;
813 }
814
815 if (m_Allocator == 0 || GetArrayKind() != ARRAY_VARIABILITY)
816 {
817 return false;
818 }
819
820 #ifdef NW_MOVE_ARRAY_CACHE_LINE_ALIGNMENT_ENABLED
821 TElement* elements =
822 static_cast<TElement*>(m_Allocator->Alloc(sizeof(TElement) * reserveSize, MEMORY_ALIGNMENT));
823 #else
824 TElement* elements =
825 static_cast<TElement*>(m_Allocator->Alloc(sizeof(TElement) * reserveSize));
826 #endif
827 NW_ASSERT(0 != elements);
828
829 size_t elementsCount = 0;
830 if (!empty())
831 {
832 std::uninitialized_copy(begin(), end(), NW_CHECKED_ARRAY_ITERATOR(elements, reserveSize));
833 elementsCount = size();
834 }
835
836 if (0 != m_Elements)
837 {
838 NW_ASSERT(0 != m_Allocator);
839 m_Allocator->Free(m_Elements);
840 }
841
842 m_Elements = elements;
843 m_End = elements + elementsCount;
844 SetCapacity(reserveSize);
845
846 return true;
847 #else
848 if (reserveSize <= capacity())
849 {
850 return true;
851 }
852 NW_FATAL_ERROR("Can't increase capacity.");
853 return false;
854 #endif
855 }
856
857 //---------------------------------------------------------------------------
858 //! @brief 末尾に要素を追加します。
859 //! 要素が追加できなかった場合、返り値に false を返します。
860 //!
861 //! @tparam TElement 要素の型です。
862 //!
863 //! @param[in] element 追加する要素への参照です。
864 //---------------------------------------------------------------------------
865 template<typename TElement>
866 NW_INLINE bool
push_back(const TElement & element)867 MoveArray<TElement>::push_back(
868 const TElement& element
869 )
870 {
871 bool result = true;
872 int capacity = GetCapacity();
873 if (capacity <= size())
874 {
875 #ifdef NW_MOVE_ARRAY_VARIABILITY_ENABLED
876 int newCapacity = (capacity == 0) ? 1 : capacity * 2;
877 result = reserve(newCapacity);
878 #else
879 result = false;
880 #endif
881 }
882
883 if (result)
884 {
885 construct(m_End, element);
886 ++m_End;
887 }
888 return result;
889 }
890
891 //---------------------------------------------------------------------------
892 //! @brief 末尾の要素を破棄します。
893 //!
894 //! @tparam TElement 要素の型です。
895 //---------------------------------------------------------------------------
896 template<typename TElement>
897 NW_INLINE void
pop_back()898 MoveArray<TElement>::pop_back()
899 {
900 if (!empty())
901 {
902 destroy(m_End - 1);
903 --m_End;
904 }
905 }
906
907 //---------------------------------------------------------------------------
908 //! @brief 指定数の要素を引数 element で埋めます。
909 //! 全ての要素が追加できなかった場合、返り値に false を返します。
910 //!
911 //! @tparam TElement 要素の型です。
912 //!
913 //! @param[in] size 割り当てるサイズです。
914 //! @param[in] element 要素を埋める値です。
915 //!
916 //! @return 指定通りの数分値を書き込めたら true を返します。
917 //---------------------------------------------------------------------------
918 template<typename TElement>
919 NW_INLINE bool
assign(int size,const TElement & element)920 MoveArray<TElement>::assign(
921 int size,
922 const TElement& element
923 )
924 {
925 clear();
926 bool result = reserve(size);
927 if (!result)
928 {
929 size = capacity();
930 }
931
932 for (int i = 0; i < size; ++i)
933 {
934 push_back(element);
935 }
936
937 return result;
938 }
939
940 //---------------------------------------------------------------------------
941 //! @brief 配列の内容を入れ替えます。
942 //!
943 //! @tparam TElement 配列要素の型です。
944 //!
945 //! @param[in] other 入れ替える対象となる配列です。
946 //---------------------------------------------------------------------------
947 template<typename TElement>
948 NW_INLINE void
swap(MoveArray<TElement> & other)949 MoveArray<TElement>::swap(
950 MoveArray<TElement>& other
951 )
952 {
953 if (&other == this)
954 {
955 return;
956 }
957
958 TElement* elements = m_Elements;
959 TElement* end = m_End;
960 size_t capacity = m_Capacity;
961 os::IAllocator* allocator = m_Allocator;
962
963 m_Elements = other.m_Elements;
964 m_End = other.m_End;
965 m_Capacity = other.m_Capacity;
966 m_Allocator = other.m_Allocator;
967
968 other.m_Elements = elements;
969 other.m_End = end;
970 other.m_Capacity = capacity;
971 other.m_Allocator = allocator;
972 }
973
974 //---------------------------------------------------------------------------
975 //! @brief サイズを変更します。
976 //! 指定サイズにできなかった場合、返り値に false を返します。
977 //!
978 //! @tparam TElement 要素の型です。
979 //!
980 //! @param[in] number 格納可能な TElement の個数を指定します。
981 //!
982 //! @return サイズが変更できた場合は true を返します。
983 //---------------------------------------------------------------------------
984 template<typename TElement>
985 NW_INLINE bool
resize(int number)986 MoveArray<TElement>::resize(
987 int number
988 )
989 {
990 bool result = true;
991 if (number < size())
992 {
993 int min = number;
994 if (min < 0)
995 {
996 min = 0;
997 result = false;
998 }
999 if (IsClass<TElement>::value)
1000 {
1001 for (int i = min; i < size(); ++i)
1002 {
1003 destroy(m_Elements + i);
1004 }
1005 }
1006 m_End = m_Elements + min;
1007 }
1008 else
1009 {
1010 int max = number;
1011 if (capacity() < max)
1012 {
1013 if (!reserve(max))
1014 {
1015 result = false;
1016 max = capacity();
1017 }
1018 }
1019 if (IsClass<TElement>::value)
1020 {
1021 for (int i = size(); i < max; ++i)
1022 {
1023 construct(m_Elements + i);
1024 }
1025 }
1026 m_End = m_Elements + max;
1027 }
1028 return result;
1029 }
1030
1031 //---------------------------------------------------------------------------
1032 //! @brief 指定したイテレータ以降の要素を削除します。
1033 //!
1034 //! @tparam TElement 配列要素の型です。
1035 //!
1036 //! @param[in] first 削除を開始する要素のイテレータです。
1037 //!
1038 //! @return first イテレータを返します。
1039 //---------------------------------------------------------------------------
1040 template<typename TElement> template <typename TIterator>
1041 NW_INLINE TIterator
erase(TIterator first)1042 MoveArray<TElement>::erase(
1043 TIterator first
1044 )
1045 {
1046 destroy_range(first, end());
1047 m_End = first;
1048 return first;
1049 }
1050
1051 //---------------------------------------------------------------------------
1052 //! @brief 指定したイテレータ間の要素を削除します。
1053 //!
1054 //! @tparam TElement 配列要素の型です。
1055 //!
1056 //! @param[in] first 削除を開始する要素のイテレータです。
1057 //! @param[in] last 削除を終了する要素のイテレータです。
1058 //!
1059 //! @return first イテレータを返します。
1060 //---------------------------------------------------------------------------
1061 template<typename TElement> template <typename TIterator>
1062 NW_INLINE TIterator
erase(TIterator first,TIterator last)1063 MoveArray<TElement>::erase(
1064 TIterator first,
1065 TIterator last
1066 )
1067 {
1068 TIterator dest = first;
1069 TIterator source = last;
1070 for (; dest != last && source != end(); ++dest, ++source)
1071 {
1072 destroy(dest);
1073 move_construct(dest, *source);
1074 }
1075
1076 if (dest != last)
1077 {
1078 destroy_range(dest, last);
1079 destroy_range(last, end());
1080 }
1081 else
1082 {
1083 for (; source != end(); ++dest, ++source)
1084 {
1085 destroy(dest);
1086 move_construct(dest, *source);
1087 }
1088 destroy_range(dest, end());
1089 }
1090
1091 m_End = dest;
1092
1093 return first;
1094 }
1095
1096 } // namespace ut
1097 } // namespace nw
1098
1099 //---------------------------------------------------------------------------
1100 //! @brief MoveArray 同士を比較する等価演算子です。
1101 //!
1102 //! @tparam TElement 配列要素の型です。
1103 //!
1104 //! @param[in] lhs 左辺値です。
1105 //! @param[in] rhs 右辺値です。
1106 //!
1107 //! @return 左辺値と右辺値の内容が同じであれば true を返します。
1108 //---------------------------------------------------------------------------
1109 template<typename TElement>
1110 NW_INLINE bool
1111 operator == (
1112 const nw::ut::MoveArray<TElement>& lhs,
1113 const nw::ut::MoveArray<TElement>& rhs
1114 )
1115 {
1116 if (lhs.size() != rhs.size())
1117 {
1118 return false;
1119 }
1120 return std::equal(lhs.begin(), lhs.end(), rhs.begin());
1121 }
1122
1123 //---------------------------------------------------------------------------
1124 //! @brief MoveArray 同士を比較する不等価演算子です。
1125 //!
1126 //! @tparam TElement 配列要素の型です。
1127 //!
1128 //! @param[in] lhs 左辺値です。
1129 //! @param[in] rhs 右辺値です。
1130 //!
1131 //! @return 左辺値と右辺値の内容が同じでなければ true を返します。
1132 //---------------------------------------------------------------------------
1133 template<typename TElement>
1134 NW_INLINE bool
1135 operator != (
1136 const nw::ut::MoveArray<TElement>& lhs,
1137 const nw::ut::MoveArray<TElement>& rhs
1138 )
1139 {
1140 if (lhs.size() != rhs.size())
1141 {
1142 return false;
1143 }
1144 return !(lhs == rhs);
1145 }
1146
1147 //---------------------------------------------------------------------------
1148 //! @brief MoveArray 同士の左辺値のが小さいかを比較する不等価演算子です。
1149 //!
1150 //! @tparam TElement 配列要素の型です。
1151 //!
1152 //! @param[in] lhs 左辺値です。
1153 //! @param[in] rhs 右辺値です。
1154 //!
1155 //! @return 左辺値が右辺値より小さい場合に true を返します。
1156 //---------------------------------------------------------------------------
1157 template<typename TElement>
1158 NW_INLINE bool
1159 operator < (
1160 const nw::ut::MoveArray<TElement>& lhs,
1161 const nw::ut::MoveArray<TElement>& rhs
1162 )
1163 {
1164 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1165 }
1166
1167 //---------------------------------------------------------------------------
1168 //! @brief MoveArray 同士の左辺値のが大きいかを比較する不等価演算子です。
1169 //!
1170 //! @tparam TElement 配列要素の型です。
1171 //!
1172 //! @param[in] lhs 左辺値です。
1173 //! @param[in] rhs 右辺値です。
1174 //!
1175 //! @return 左辺値が右辺値より大きい場合に true を返します。
1176 //---------------------------------------------------------------------------
1177 template<typename TElement>
1178 NW_INLINE bool
1179 operator > (
1180 const nw::ut::MoveArray<TElement>& lhs,
1181 const nw::ut::MoveArray<TElement>& rhs
1182 )
1183 {
1184 return rhs < lhs;
1185 }
1186
1187 //---------------------------------------------------------------------------
1188 //! @brief MoveArray 同士の左辺値のが小さいまたは等しいかを比較する不等価演算子です。
1189 //!
1190 //! @tparam TElement 配列要素の型です。
1191 //!
1192 //! @param[in] lhs 左辺値です。
1193 //! @param[in] rhs 右辺値です。
1194 //!
1195 //! @return 左辺値が右辺値より小さいか等しい場合に true を返します。
1196 //---------------------------------------------------------------------------
1197 template<typename TElement>
1198 NW_INLINE bool
1199 operator <= (
1200 const nw::ut::MoveArray<TElement>& lhs,
1201 const nw::ut::MoveArray<TElement>& rhs
1202 )
1203 {
1204 return !(rhs < lhs);
1205 }
1206
1207 //---------------------------------------------------------------------------
1208 //! @brief MoveArray 同士の左辺値のが大きいまたは等しいかを比較する不等価演算子です。
1209 //!
1210 //! @tparam TElement 配列要素の型です。
1211 //!
1212 //! @param[in] lhs 左辺値です。
1213 //! @param[in] rhs 右辺値です。
1214 //!
1215 //! @return 左辺値が右辺値より大きいか等しい場合に true を返します。
1216 //---------------------------------------------------------------------------
1217 template<typename TElement>
1218 NW_INLINE bool
1219 operator >= (
1220 const nw::ut::MoveArray<TElement>& lhs,
1221 const nw::ut::MoveArray<TElement>& rhs
1222 )
1223 {
1224 return !(lhs < rhs);
1225 }
1226
1227 #endif // NW_UT_MOVEARRAY_H_
1228