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