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