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