-
Notifications
You must be signed in to change notification settings - Fork 0
/
integer_tuple.hpp
113 lines (91 loc) · 3.04 KB
/
integer_tuple.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#pragma once
#include <iostream>
//solution to exercice 1
#include "static_if.hpp"
namespace detail_ {
template <int Index>
struct position{
static_assert((Index > 0), "Index should be > 0");
constexpr position(int val) : value{val}
{}
static const int index=Index;
int value;
};
template <std::size_t N>
constexpr int initialize( )
{
return 0;
}
template <std::size_t N, typename X>
constexpr int initialize( X x )
{
return X::index==N?x.value:initialize<N>();
}
template <std::size_t N, typename X, typename ... Rest>
constexpr int initialize(X x, Rest ... rest )
{
return X::index==N?x.value:initialize<N>(rest...);
}
template<std::size_t NDim, std::size_t Index >
struct sized_integer_tuple
: public sized_integer_tuple<NDim, Index-1>
{
private:
static const std::size_t n_dim=NDim;
typedef sized_integer_tuple<NDim, Index-1> super;
static const std::size_t n_args=Index;
template <std::size_t Limit>
static constexpr bool check_bounds() {
return true;
};
template <std::size_t Limit, typename _First, typename ...Elems>
static constexpr bool check_bounds() {
return (_First::index <= Limit) && check_bounds<Limit, Elems...>();
};
public:
template <int Idx, typename... GenericElements>
constexpr sized_integer_tuple ( position<Idx> const& t,
GenericElements const& ... x):
super( t, x... ),
m_offset(initialize<n_dim-n_args+1>(t, x...)) {
static_assert(check_bounds<n_dim,
position<Idx>,
GenericElements...>(), "Out of bound");
}
constexpr sized_integer_tuple ():
super(),
m_offset(initialize<n_dim-n_args+1>())
{ }
template<int Idx>
constexpr int get() const {
return static_if<NDim-Idx==n_args-1>
::apply(m_offset, super::template get<Idx>());
}
protected:
int m_offset;
};
//recursion anchor
template< std::size_t NDim >
struct sized_integer_tuple<NDim, 0>
{
static const std::size_t n_dim=NDim;
template <typename... GenericElements>
constexpr sized_integer_tuple ( GenericElements... ) {}
constexpr sized_integer_tuple ( ) {}
static const std::size_t n_args=0;
//never called
template<int Idx>
constexpr int get() const {
static_assert((Idx<=n_dim),
"sized_integer_tuple out of bound access in get<>");
return 0;
}
};
} //namespace detail_
template<int Index, typename Type>
auto constexpr pos(Type value){
static_assert((Index > 0), "Index should be > 0");
return detail_::position<Index>(value);
}
template<std::size_t Length>
using integer_tuple=detail_::sized_integer_tuple<Length, Length>;