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