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