Last active
January 13, 2016 13:37
-
-
Save 2bbb/f1a167dfdd23fbd2033e to your computer and use it in GitHub Desktop.
flex_array
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <iostream> | |
| #include <array> | |
| namespace bbb { | |
| template <typename type> | |
| using get_type = typename type::type; | |
| namespace sequences { | |
| template <typename type, type ... ns> | |
| struct integer_sequence { | |
| using value_type = type; | |
| static constexpr std::size_t size() noexcept { return sizeof...(ns); } | |
| }; | |
| namespace impl { | |
| template <typename t> | |
| struct wrapper { using type = t; }; | |
| template <typename integer_type, integer_type n, integer_type ... ns> | |
| struct make_integer_sequence { | |
| using type = get_type<get_type<std::conditional< | |
| n == 0, | |
| wrapper<integer_sequence<integer_type, ns ...>>, | |
| make_integer_sequence<integer_type, n - 1, n - 1, ns ...> | |
| >>>; | |
| }; | |
| }; | |
| template <typename type, type n> | |
| using make_integer_sequence = get_type<impl::make_integer_sequence<type, n>>; | |
| template <std::size_t ... ns> | |
| using index_sequence = integer_sequence<std::size_t, ns ...>; | |
| template <std::size_t n> | |
| using make_index_sequence = make_integer_sequence<std::size_t, n>; | |
| template <typename... types> | |
| using index_sequence_for = make_index_sequence<sizeof...(types)>; | |
| }; | |
| using namespace sequences; | |
| template <std::size_t size, std::size_t ... sizes> | |
| struct multiply { | |
| static constexpr std::size_t value = size * multiply<sizes ...>::value; | |
| }; | |
| template <std::size_t size> | |
| struct multiply<size> { | |
| static constexpr std::size_t value = size; | |
| }; | |
| template <typename value_t, std::size_t size_, std::size_t ... sizes> | |
| struct flex_array { | |
| using value_type = value_t; | |
| using inner_flex_array = flex_array<value_type, sizes ...>; | |
| std::array<inner_flex_array *, size_> arr; | |
| template <std::size_t ... indecies> | |
| flex_array(value_type *body, std::size_t offset, index_sequence<indecies ...>) | |
| : arr({new flex_array<value_t, sizes ...>(body, offset + indecies * multiply<sizes ...>::value) ...}) {} | |
| flex_array(value_type *body, std::size_t offset = 0) | |
| : flex_array(body, offset, make_index_sequence<size_>()) {} | |
| std::size_t size() const { return size_; } | |
| std::size_t rank() const { return sizeof...(sizes) + 1; } | |
| flex_array<value_t, sizes ...> &operator[](std::size_t index) { return *(arr[index]); } | |
| const flex_array<value_t, sizes ...> &operator[](std::size_t index) const { return *(arr[index]); } | |
| }; | |
| template <typename value_t, std::size_t size_> | |
| struct flex_array<value_t, size_> { | |
| using value_type = value_t; | |
| value_type * const body; | |
| flex_array(value_type *body, std::size_t offset = 0) | |
| : body(body + offset) {} | |
| std::size_t size() const { return size_; } | |
| std::size_t rank() const { return 1; } | |
| value_type &operator[](std::size_t index) { return body[index]; } | |
| const value_type &operator[](std::size_t index) const { return body[index]; } | |
| }; | |
| }; | |
| int main(int argc, char *argv[]) { | |
| int *x = new int[64]; | |
| for(std::size_t i = 0; i < 64; i++) { x[i] = i + 1; } | |
| bbb::flex_array<int, 4, 4, 4> xs(x); | |
| std::cout << "xs.rank(): " << xs.rank() << std::endl; | |
| for(std::size_t i = 0; i < 3; i++) std::cout << xs[i][i][i] << ", "; | |
| std::cout << xs[3][3][3] << std::endl; | |
| bbb::flex_array<int, 32, 2> ys(x); | |
| std::cout << "ys.rank(): " << ys.rank() << std::endl; | |
| std::cout << ys[16][0] << ", " << ys[16][1] << ", " << ys[17][0]; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment