fork(2) download
  1. #include <iostream>
  2. #include <vector>
  3. #include <iterator>
  4. #include <array>
  5.  
  6. namespace details {
  7. template<
  8. class R,
  9. class iterator_traits,
  10. class iterator_category,
  11. bool is_random_access=std::is_base_of<
  12. std::random_access_iterator_tag,
  13. iterator_category
  14. >::value
  15. >
  16. struct random_access_support {};
  17. template<class R, class iterator_traits, class iterator_category>
  18. struct random_access_support<R, iterator_traits, iterator_category, true> {
  19. R const* self() const { return static_cast<R const*>(this); }
  20. template<class S>
  21. typename iterator_traits::reference operator[](S&&s) const {
  22. return self()->begin()[std::forward<S>(s)];
  23. }
  24. std::size_t size() const { return self()->end()-self()->begin(); }
  25. };
  26. }
  27.  
  28. template<class It>
  29. struct range:details::random_access_support<
  30. range<It>,
  31. std::iterator_traits<It>,
  32. typename std::iterator_traits<It>::iterator_category
  33. > {
  34. using value_type = typename std::iterator_traits<It>::value_type;
  35. using reference = typename std::iterator_traits<It>::reference;
  36. using iterator = It;
  37. using iterator_category = typename std::iterator_traits<It>::iterator_category;
  38. using pointer = typename std::iterator_traits<It>::pointer;
  39.  
  40. It begin() const { return b; }
  41. It end() const { return e; }
  42.  
  43. bool empty() const { return b==e; }
  44. reference front() const { return *b; }
  45. reference back() const { return *std::prev(e); }
  46.  
  47. range( It s, It f ):b(s),e(f) {}
  48.  
  49. range()=default;
  50. range(range const&)=default;
  51. range& operator=(range const&)=default;
  52. private:
  53. It b; It e;
  54. };
  55.  
  56. namespace details {
  57. template<class T>
  58. struct array_view_helper:range<T*> {
  59. using non_const_T = typename std::remove_const<T>::type;
  60. T* data() const { return this->begin(); }
  61.  
  62. array_view_helper( array_view_helper const& ) = default;
  63. array_view_helper():range<T*>(nullptr, nullptr){}
  64. array_view_helper& operator=(array_view_helper const&)=default;
  65.  
  66. template<class A>
  67. explicit operator std::vector<non_const_T, A>() const {
  68. return { this->begin(), this->end() };
  69. }
  70. std::vector<non_const_T> as_vector() const {
  71. return std::vector<non_const_T>(*this);
  72. }
  73.  
  74. template<std::size_t N>
  75. array_view_helper( T(&arr)[N] ):range<T*>(arr+0, arr+N) {}
  76. template<std::size_t N>
  77. array_view_helper( std::array<T,N>&arr ):range<T*>(arr.data(), arr.data()+N) {}
  78. template<class A>
  79. array_view_helper( std::vector<T,A>&vec ):range<T*>(vec.data(), vec.data()+vec.size()) {}
  80. array_view_helper( T*s, T*f ):range<T*>(s,f) {}
  81. };
  82. }
  83. // non-const
  84. template<class T>
  85. struct array_view:details::array_view_helper<T> {
  86. using base = details::array_view_helper<T>;
  87.  
  88. // using base::base in C++11 compliant compilers:
  89. template<std::size_t N>
  90. array_view( T(&arr)[N] ):base(arr) {}
  91. template<std::size_t N>
  92. array_view( std::array<T,N>&arr ):base(arr) {}
  93. template<class A>
  94. array_view( std::vector<T,A>&vec ):base(vec) {}
  95. array_view( T*s, T*f ):base(s,f) {}
  96.  
  97. // special methods:
  98. array_view( array_view const& ) = default;
  99. array_view() = default;
  100. array_view& operator=(array_view const&)=default;
  101. };
  102. template<class T>
  103. struct array_view<T const>:details::array_view_helper<const T> {
  104. using base = details::array_view_helper<const T>;
  105.  
  106. // using base::base in C++11 compliant compilers:
  107. template<std::size_t N>
  108. array_view( T(&arr)[N] ):base(arr) {}
  109. template<std::size_t N>
  110. array_view( std::array<T,N>&arr ):base(arr) {}
  111. template<class A>
  112. array_view( std::vector<T,A>&vec ):base(vec) {}
  113. array_view( T*s, T*f ):base(s,f) {}
  114.  
  115. // special methods:
  116. array_view( array_view const& ) = default;
  117. array_view() = default;
  118. array_view& operator=(array_view const&)=default;
  119.  
  120. // const T only constructors:
  121. template<std::size_t N>
  122. array_view( std::array<T,N> const&arr ):base(arr.data(), arr.data()+N) {}
  123. template<std::size_t N>
  124. array_view( std::array<T const,N> const&arr ):base(arr.data(), arr.data()+N) {}
  125. template<class A>
  126. array_view( std::vector<T,A> const&vec ):base(vec.data(), vec.data()+vec.size()) {}
  127. };
  128.  
  129. void foo( array_view<int> v ) {
  130. for(auto x: v) {
  131. std::cout << x << ",";
  132. }
  133. std::cout << "\n";
  134. v[1] = 3;
  135. for(auto x: v) {
  136. std::cout << x << ",";
  137. }
  138. std::cout << "\n";
  139. }
  140.  
  141. int main() {
  142. std::vector<int> v = {1,2,3};
  143. foo(v);
  144. }
  145.  
Success #stdin #stdout 0s 3428KB
stdin
Standard input is empty
stdout
1,2,3,
1,3,3,