coder_array.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /* Copyright 2019 The Mathworks, Inc. */
  2. /* Copied from
  3. * fullfile(matlabroot,'extern','include','coder','coder_array','coder_array_rtw_cpp11.h') */
  4. #ifndef _mw_coder_array_cpp11_h
  5. #define _mw_coder_array_cpp11_h
  6. // Usage:
  7. //
  8. // coder::array<T, N>: T base type of data, N number of dimensions
  9. //
  10. // coder::array()
  11. // : default constructor
  12. // coder::array(coder::array const &)
  13. // : copy constructor (always make a deep copy of other array)
  14. // coder::array(T const *data, SizeType const *sz)
  15. // : Set data with sizes of this array.
  16. // : (Data is not copied, data is not deleted)
  17. // coder::array::operator = (coder coder::array &)
  18. // : Assign into this array;
  19. // : delete its previous contents (if owning the data.)
  20. // set(T const *data, SizeType sz1, SizeType sz2, ...)
  21. // : Set data with dimensions.
  22. // : (Data is not copied, data is not deleted)
  23. // set_size(SizeType sz1, SizeType sz2, ...)
  24. // : Set sizes of array. Reallocate memory of data if needed.
  25. // bool is_owner() : Return true if the data is owned by the class.
  26. // void set_owner(b) : Set if the data is owned by the class.
  27. // SizeType capacity() : How many entries are reserved by memory allocation.
  28. // reshape( SizeType sz1, SizeType sz2, ...)
  29. // : Reshape array to a different ND shape. Do not copy the data.
  30. // : The number of elements must not be changed (numel()==sz1*sz2*...)
  31. // : Return the array with possibly new number of dimensions.
  32. // clear() : Reset array to be empty.
  33. // SizeType numel() : Return the number of elements.
  34. // operator [] (SizeType index) : Extract element at linear index (0 based.)
  35. // size(SizeType dimension) : Size of array of the provided dimension.
  36. // SizeType * size() : Return the pointer to all the sizes of this array.
  37. // SizeType index(SizeType i1, SizeType i2, ...)
  38. // : Compute the linear index from ND index (i1,i2,...)
  39. // at(SizeType i1, SizeType i2, ...) : The element at index (i1,i2,...)
  40. #include <cassert>
  41. #include <cstring>
  42. #include <iterator>
  43. #include <string>
  44. #include <vector>
  45. #ifndef INT32_T
  46. #include "rtwtypes.h"
  47. #endif
  48. namespace coder {
  49. #ifndef CODER_ARRAY_NEW_DELETE
  50. #define CODER_ARRAY_NEW_DELETE
  51. #define CODER_NEW(T, N) new T[N]
  52. #define CODER_DELETE(P) delete[](P)
  53. #endif
  54. using SizeType = int32_T;
  55. namespace std = ::std;
  56. namespace detail {
  57. #ifndef CODER_ARRAY_DATA_PTR_DEFINED
  58. template <typename T, typename SZ>
  59. class data_ptr {
  60. public:
  61. using value_type = T;
  62. using size_type = SZ;
  63. data_ptr()
  64. : data_(nullptr)
  65. , size_(0)
  66. , capacity_(0)
  67. , owner_(false) {
  68. }
  69. data_ptr(T* _data, SZ _sz)
  70. : data_(_data)
  71. , size_(_sz)
  72. , capacity_(_sz)
  73. , owner_(false) {
  74. }
  75. data_ptr(data_ptr const& _other)
  76. : data_(_other.owner_ ? nullptr : _other.data_)
  77. , size_(_other.owner_ ? 0 : _other.size_)
  78. , capacity_(_other.owner_ ? 0 : _other.capacity_)
  79. , owner_(_other.owner_) {
  80. if (owner_) {
  81. resize(_other.size_);
  82. (void)std::copy(_other.data_, _other.data_ + size_, data_);
  83. }
  84. }
  85. ~data_ptr() {
  86. if (owner_) {
  87. CODER_DELETE(data_);
  88. }
  89. }
  90. SZ capacity() const {
  91. return capacity_;
  92. }
  93. void reserve(SZ _n) {
  94. if (_n > capacity_) {
  95. T* const new_data{CODER_NEW(T, _n)};
  96. (void)std::copy(data_, data_ + size_, new_data);
  97. if (owner_) {
  98. CODER_DELETE(data_);
  99. }
  100. data_ = new_data;
  101. capacity_ = _n;
  102. owner_ = true;
  103. }
  104. }
  105. void resize(SZ _n) {
  106. reserve(_n);
  107. size_ = _n;
  108. }
  109. private:
  110. // Prohibit use of assignment operator to prevent subtle bugs
  111. void operator=(data_ptr<T, SZ> const& _other);
  112. public:
  113. void set(T* _data, SZ _sz) {
  114. if (owner_) {
  115. CODER_DELETE(data_);
  116. }
  117. data_ = _data;
  118. size_ = _sz;
  119. owner_ = false;
  120. capacity_ = size_;
  121. }
  122. void copy(T const* const _data, SZ _size) {
  123. if (data_ == _data) {
  124. size_ = _size;
  125. return;
  126. }
  127. if (owner_) {
  128. CODER_DELETE(data_);
  129. }
  130. data_ = CODER_NEW(T, _size);
  131. owner_ = true;
  132. size_ = _size;
  133. capacity_ = size_;
  134. (void)std::copy(_data, _data + _size, data_);
  135. }
  136. void copy(data_ptr<T, SZ> const& _other) {
  137. copy(_other.data_, _other.size_);
  138. }
  139. operator T*() {
  140. return &data_[0];
  141. }
  142. operator T const *() const {
  143. return &data_[0];
  144. }
  145. T& operator[](SZ _index) {
  146. return data_[_index];
  147. }
  148. T const& operator[](SZ _index) const {
  149. return data_[_index];
  150. }
  151. T* operator->() {
  152. return data_;
  153. }
  154. T const* operator->() const {
  155. return data_;
  156. }
  157. bool is_null() const {
  158. return data_ == nullptr;
  159. }
  160. void clear() {
  161. if (owner_) {
  162. CODER_DELETE(data_);
  163. }
  164. data_ = nullptr;
  165. size_ = 0;
  166. capacity_ = 0;
  167. owner_ = false;
  168. }
  169. bool is_owner() const {
  170. return owner_;
  171. }
  172. void set_owner(bool _b) {
  173. owner_ = _b;
  174. }
  175. private:
  176. T* data_;
  177. SZ size_;
  178. SZ capacity_;
  179. bool owner_;
  180. };
  181. #endif
  182. } // namespace detail
  183. // Implementing the random access iterator class so coder::array can be
  184. // used in STL iterators.
  185. template <typename T>
  186. class array_iterator : public std::iterator<std::random_access_iterator_tag,
  187. typename T::value_type,
  188. typename T::size_type> {
  189. public:
  190. array_iterator()
  191. : arr_(nullptr)
  192. , i_(0) {
  193. }
  194. array_iterator(array_iterator<T> const& other)
  195. : arr_(other.arr_)
  196. , i_(other.i_) {
  197. }
  198. ~array_iterator() {
  199. }
  200. typename T::value_type& operator*() const {
  201. return (*arr_)[i_];
  202. }
  203. typename T::value_type* operator->() const {
  204. return &(*arr_)[i_];
  205. }
  206. typename T::value_type& operator[](typename T::size_type _di) const {
  207. return (*arr_)[i_ + _di];
  208. }
  209. array_iterator<T>& operator++() {
  210. ++i_;
  211. return *this;
  212. }
  213. array_iterator<T>& operator--() {
  214. --i_;
  215. return *this;
  216. }
  217. array_iterator<T> operator++(int) {
  218. array_iterator<T> cp{*this};
  219. ++i_;
  220. return cp;
  221. }
  222. array_iterator<T> operator--(int) {
  223. array_iterator<T> cp{*this};
  224. --i_;
  225. return cp;
  226. }
  227. array_iterator<T>& operator=(array_iterator<T> const& _other) {
  228. this->i_ = _other.i_;
  229. return *this;
  230. }
  231. bool operator==(array_iterator<T> const& _other) const {
  232. return i_ == _other.i_;
  233. }
  234. bool operator!=(array_iterator<T> const& _other) const {
  235. return i_ != _other.i_;
  236. }
  237. bool operator<(array_iterator<T> const& _other) const {
  238. return i_ < _other.i_;
  239. }
  240. bool operator>(array_iterator<T> const& _other) const {
  241. return i_ > _other.i_;
  242. }
  243. bool operator<=(array_iterator<T> const& _other) const {
  244. return i_ <= _other.i_;
  245. }
  246. bool operator>=(array_iterator<T> const& _other) const {
  247. return i_ >= _other.i_;
  248. }
  249. array_iterator<T> operator+(typename T::size_type _add) const {
  250. array_iterator<T> cp{*this};
  251. cp.i_ += _add;
  252. return cp;
  253. }
  254. array_iterator<T>& operator+=(typename T::size_type _add) {
  255. this->i_ += _add;
  256. return *this;
  257. }
  258. array_iterator<T> operator-(typename T::size_type _subtract) const {
  259. array_iterator<T> cp{*this};
  260. cp.i_ -= _subtract;
  261. return cp;
  262. }
  263. array_iterator<T>& operator-=(typename T::size_type _subtract) {
  264. this->i_ -= _subtract;
  265. return *this;
  266. }
  267. typename T::size_type operator-(array_iterator<T> const& _other) const {
  268. return static_cast<typename T::size_type>(this->i_ - _other.i_);
  269. }
  270. array_iterator(T* _arr, typename T::size_type _i)
  271. : arr_(_arr)
  272. , i_(_i) {
  273. }
  274. private:
  275. T* arr_;
  276. typename T::size_type i_;
  277. };
  278. // Const version of the array iterator.
  279. template <typename T>
  280. class const_array_iterator : public std::iterator<std::random_access_iterator_tag,
  281. typename T::value_type,
  282. typename T::size_type> {
  283. public:
  284. const_array_iterator()
  285. : arr_(nullptr)
  286. , i_(0) {
  287. }
  288. const_array_iterator(const_array_iterator<T> const& other)
  289. : arr_(other.arr_)
  290. , i_(other.i_) {
  291. }
  292. ~const_array_iterator() {
  293. }
  294. typename T::value_type const& operator*() const {
  295. return (*arr_)[i_];
  296. }
  297. typename T::value_type const* operator->() const {
  298. return &(*arr_)[i_];
  299. }
  300. typename T::value_type const& operator[](typename T::size_type _di) const {
  301. return (*arr_)[i_ + _di];
  302. }
  303. const_array_iterator<T>& operator++() {
  304. ++i_;
  305. return *this;
  306. }
  307. const_array_iterator<T>& operator--() {
  308. --i_;
  309. return *this;
  310. }
  311. const_array_iterator<T> operator++(int) {
  312. const_array_iterator<T> copy{*this};
  313. ++i_;
  314. return copy;
  315. }
  316. const_array_iterator<T> operator--(int) {
  317. const_array_iterator copy{*this};
  318. --i_;
  319. return copy;
  320. }
  321. const_array_iterator<T>& operator=(const_array_iterator<T> const& _other) {
  322. this->i_ = _other.i_;
  323. return *this;
  324. }
  325. bool operator==(const_array_iterator<T> const& _other) const {
  326. return i_ == _other.i_;
  327. }
  328. bool operator!=(const_array_iterator<T> const& _other) const {
  329. return i_ != _other.i_;
  330. }
  331. bool operator<(const_array_iterator<T> const& _other) const {
  332. return i_ < _other.i_;
  333. }
  334. bool operator>(const_array_iterator<T> const& _other) const {
  335. return i_ > _other.i_;
  336. }
  337. bool operator<=(const_array_iterator<T> const& _other) const {
  338. return i_ <= _other.i_;
  339. }
  340. bool operator>=(const_array_iterator<T> const& _other) const {
  341. return i_ >= _other.i_;
  342. }
  343. const_array_iterator<T> operator+(typename T::size_type _add) const {
  344. const_array_iterator<T> cp{*this};
  345. cp.i_ += _add;
  346. return cp;
  347. }
  348. const_array_iterator<T>& operator+=(typename T::size_type _add) {
  349. this->i_ += _add;
  350. return *this;
  351. }
  352. const_array_iterator<T> operator-(typename T::size_type _subtract) const {
  353. const_array_iterator<T> cp{*this};
  354. cp.i_ -= _subtract;
  355. return cp;
  356. }
  357. const_array_iterator<T>& operator-=(typename T::size_type _subtract) {
  358. this->i_ -= _subtract;
  359. return *this;
  360. }
  361. typename T::size_type operator-(const_array_iterator<T> const& _other) const {
  362. return static_cast<typename T::size_type>(this->i_ - _other.i_);
  363. }
  364. const_array_iterator(T const* _arr, typename T::size_type _i)
  365. : arr_(_arr)
  366. , i_(_i) {
  367. }
  368. private:
  369. T const* arr_;
  370. typename T::size_type i_;
  371. typename T::size_type n_;
  372. };
  373. namespace detail {
  374. // detail::numel<N>: Compile-time product of the given size vector of length N.
  375. template <int N>
  376. class numel {
  377. public:
  378. template <typename SZ>
  379. static SZ compute(SZ _size[]) {
  380. return _size[N - 1] * numel<N - 1>::compute(_size);
  381. }
  382. };
  383. template <>
  384. class numel<0> {
  385. public:
  386. template <typename SZ>
  387. static SZ compute(SZ[]) {
  388. return 1;
  389. }
  390. };
  391. // Compute the product for a set of numeric arguments: product<int32_T>(10, 20, 30, ...) =>
  392. // 10*20*30*...
  393. template <typename SZ, typename First, typename... Rest>
  394. struct product_i {
  395. static SZ compute(First _f, Rest... _rest) {
  396. return _f * product_i<SZ, Rest...>::compute(_rest...);
  397. }
  398. };
  399. template <typename SZ, typename Last>
  400. struct product_i<SZ, Last> {
  401. static SZ compute(Last _l) {
  402. return _l;
  403. }
  404. };
  405. template <typename SZ, typename... Args>
  406. SZ product(Args... args) {
  407. return product_i<SZ, Args...>::compute(args...);
  408. }
  409. // Compute flat index from (column-major) ND size vector and a list of indices.
  410. template <int I>
  411. class index_nd {
  412. public:
  413. template <typename SZ>
  414. static SZ compute(SZ const _size[], SZ const _indices[]) {
  415. SZ const weight{numel<I - 1>::compute(_size)};
  416. return weight * _indices[I - 1] + index_nd<I - 1>::compute(_size, _indices);
  417. }
  418. };
  419. template <>
  420. class index_nd<0> {
  421. public:
  422. template <typename SZ>
  423. static SZ compute(SZ[], SZ[]) {
  424. return 0;
  425. }
  426. };
  427. template <bool Cond>
  428. struct match_dimensions {};
  429. template <>
  430. struct match_dimensions<true> {
  431. static void check() {
  432. }
  433. };
  434. } // namespace detail
  435. // Base class for code::array. SZ is the type used for sizes (currently int32_t.)
  436. // Overloading up to 10 dimensions (not using variadic templates to
  437. // stay compatible with C++98.)
  438. template <typename T, typename SZ, int N>
  439. class array_base {
  440. public:
  441. using value_type = T;
  442. using size_type = SZ;
  443. array_base() {
  444. (void)::memset(size_, 0, sizeof(SZ) * N);
  445. }
  446. array_base(T* _data, SZ const* _sz)
  447. : data_(_data, coder::detail::numel<N>::compute(_sz)) {
  448. (void)std::copy(_sz, _sz + N, size_);
  449. }
  450. array_base& operator=(array_base const& _other) {
  451. data_.copy(_other.data_);
  452. (void)std::copy(_other.size_, _other.size_ + N, size_);
  453. return *this;
  454. }
  455. template <typename... Dims>
  456. void set(T* _data, Dims... dims) {
  457. coder::detail::match_dimensions<N == sizeof...(dims)>::check();
  458. data_.set(_data, coder::detail::product<SZ>(dims...));
  459. set_size_i<0>(dims...);
  460. }
  461. bool is_owner() const {
  462. return data_.is_owner();
  463. }
  464. void set_owner(bool b) {
  465. data_.set_owner(b);
  466. }
  467. SZ capacity() const {
  468. return data_.capacity();
  469. }
  470. private:
  471. template <SZ _i, typename First, typename... Rest>
  472. void set_size_i(First f, Rest... rest) {
  473. size_[_i] = f;
  474. set_size_i<_i + 1, Rest...>(rest...);
  475. }
  476. template <SZ _i, typename Last>
  477. void set_size_i(Last l) {
  478. size_[_i] = l;
  479. }
  480. public:
  481. template <typename... Dims>
  482. void set_size(Dims... dims) {
  483. coder::detail::match_dimensions<N == sizeof...(dims)>::check();
  484. set_size_i<0>(dims...);
  485. ensureCapacity(numel());
  486. }
  487. template <SizeType N1>
  488. array_base<T, SZ, N1> reshape_n(SZ const (&_ns)[N1]) const {
  489. array_base<T, SZ, N1> reshaped{const_cast<T*>(&data_[0]), _ns};
  490. return reshaped;
  491. }
  492. template <typename... Dims>
  493. array_base<T, SZ, static_cast<SZ>(sizeof...(Dims))> reshape(Dims... dims) const {
  494. SZ const ns[]{static_cast<SZ>(dims)...};
  495. return reshape_n(ns);
  496. }
  497. T& operator[](SZ _index) {
  498. return data_[_index];
  499. }
  500. T const& operator[](SZ _index) const {
  501. return data_[_index];
  502. }
  503. void clear() {
  504. data_.clear();
  505. }
  506. T* data() {
  507. return data_;
  508. }
  509. T const* data() const {
  510. return data_;
  511. }
  512. SZ const* size() const {
  513. return &size_[0];
  514. }
  515. SZ size(SZ _index) const {
  516. return size_[_index];
  517. }
  518. SZ numel() const {
  519. return coder::detail::numel<N>::compute(size_);
  520. }
  521. template <typename... Dims>
  522. SZ index(Dims... _dims) const {
  523. coder::detail::match_dimensions<N == sizeof...(_dims)>::check();
  524. SZ const indices[]{static_cast<SZ>(_dims)...};
  525. return coder::detail::index_nd<static_cast<SZ>(sizeof...(_dims))>::compute(size_, indices);
  526. }
  527. template <typename... Dims>
  528. T& at(Dims... _i) {
  529. coder::detail::match_dimensions<N == sizeof...(_i)>::check();
  530. return data_[index(_i...)];
  531. }
  532. template <typename... Dims>
  533. T const& at(Dims... _i) const {
  534. coder::detail::match_dimensions<N == sizeof...(_i)>::check();
  535. return data_[index(_i...)];
  536. }
  537. array_iterator<array_base<T, SZ, N>> begin() {
  538. return array_iterator<array_base<T, SZ, N>>(this, 0);
  539. }
  540. array_iterator<array_base<T, SZ, N>> end() {
  541. return array_iterator<array_base<T, SZ, N>>(this, this->numel());
  542. }
  543. const_array_iterator<array_base<T, SZ, N>> begin() const {
  544. return const_array_iterator<array_base<T, SZ, N>>(this, 0);
  545. }
  546. const_array_iterator<array_base<T, SZ, N>> end() const {
  547. return const_array_iterator<array_base<T, SZ, N>>(this, this->numel());
  548. }
  549. protected:
  550. coder::detail::data_ptr<T, SZ> data_;
  551. SZ size_[N];
  552. private:
  553. void ensureCapacity(SZ _newNumel) {
  554. if (_newNumel > data_.capacity()) {
  555. SZ i{data_.capacity()};
  556. if (i < 16) {
  557. i = 16;
  558. }
  559. while (i < _newNumel) {
  560. if (i > 1073741823) {
  561. i = MAX_int32_T;
  562. } else {
  563. i *= 2;
  564. }
  565. }
  566. data_.reserve(i);
  567. }
  568. data_.resize(_newNumel);
  569. }
  570. };
  571. // The standard coder::array class with base type and number of dimensions.
  572. template <typename T, int N>
  573. class array : public array_base<T, SizeType, N> {
  574. private:
  575. using Base = array_base<T, SizeType, N>;
  576. public:
  577. array()
  578. : Base() {
  579. }
  580. array(array<T, N> const& _other)
  581. : Base(_other) {
  582. }
  583. array(Base const& _other)
  584. : Base(_other) {
  585. }
  586. array(T* _data, SizeType const* _sz)
  587. : Base(_data, _sz) {
  588. }
  589. };
  590. // Specialize on char_T (row vector) for better support on strings.
  591. template <>
  592. class array<char_T, 2> : public array_base<char_T, SizeType, 2> {
  593. private:
  594. using Base = array_base<char_T, SizeType, 2>;
  595. public:
  596. array()
  597. : array_base() {
  598. }
  599. array(array<char_T, 2> const& _other)
  600. : Base(_other) {
  601. }
  602. array(Base const& _other)
  603. : Base(_other) {
  604. }
  605. array(std::string const& _str) {
  606. operator=(_str);
  607. }
  608. array(char_T const* const _str) {
  609. operator=(_str);
  610. }
  611. array(std::vector<char_T> const& _vec) {
  612. SizeType const n{static_cast<SizeType>(_vec.size())};
  613. set_size(1, n);
  614. data_.copy(&_vec[0], n);
  615. }
  616. array& operator=(std::string const& _str) {
  617. SizeType const n{static_cast<SizeType>(_str.size())};
  618. set_size(1, n);
  619. data_.copy(_str.c_str(), n);
  620. return *this;
  621. }
  622. array& operator=(char_T const* const _str) {
  623. SizeType const n{static_cast<SizeType>(strlen(_str))};
  624. set_size(1, n);
  625. data_.copy(_str, n);
  626. return *this;
  627. }
  628. operator std::string() const {
  629. return std::string(static_cast<char const*>(&(*this)[0]), static_cast<int>(size(1)));
  630. }
  631. };
  632. // Specialize on 2 dimensions for better support interactions with
  633. // std::vector and row vectors.
  634. template <typename T>
  635. class array<T, 2> : public array_base<T, SizeType, 2> {
  636. private:
  637. using Base = array_base<T, SizeType, 2>;
  638. public:
  639. array()
  640. : Base() {
  641. }
  642. array(array<T, 2> const& _other)
  643. : Base(_other) {
  644. }
  645. array(Base const& _other)
  646. : Base(_other) {
  647. }
  648. array(std::vector<T> const& _vec) {
  649. operator=(_vec);
  650. }
  651. array& operator=(std::vector<T> const& _vec) {
  652. SizeType n{static_cast<SizeType>(_vec.size())};
  653. Base::set_size(1, n);
  654. Base::data_.copy(&_vec[0], n);
  655. return *this;
  656. }
  657. operator std::vector<T>() const {
  658. T const* p{&Base::data_[0]};
  659. return std::vector<T>(p, p + Base::numel());
  660. }
  661. };
  662. // Specialize on 1 dimension for better support with std::vector and
  663. // column vectors.
  664. template <typename T>
  665. class array<T, 1> : public array_base<T, SizeType, 1> {
  666. private:
  667. using Base = array_base<T, SizeType, 1>;
  668. public:
  669. array()
  670. : Base() {
  671. }
  672. array(array<T, 1> const& _other)
  673. : Base(_other) {
  674. }
  675. array(Base const& _other)
  676. : Base(_other) {
  677. }
  678. array(std::vector<T> const& _vec) {
  679. operator=(_vec);
  680. }
  681. array& operator=(std::vector<T> const& _vec) {
  682. SizeType n{static_cast<SizeType>(_vec.size())};
  683. Base::set_size(n);
  684. Base::data_.copy(&_vec[0], n);
  685. return *this;
  686. }
  687. operator std::vector<T>() const {
  688. T const* p{&Base::data_[0]};
  689. return std::vector<T>(p, p + Base::numel());
  690. }
  691. };
  692. } // namespace coder
  693. #endif