-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlists.hpp
152 lines (123 loc) · 3.91 KB
/
lists.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
//
// Copyright (c) 2022-present DeepGrace (complex dot invoke at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/deepgrace/smp
//
#ifndef LISTS_HPP
#define LISTS_HPP
#include <tuple>
#include <cstddef>
#include <utility>
namespace smp
{
template <template <auto ...> typename T, auto... U, template <auto ...> typename V, auto... W>
constexpr decltype(auto) operator+(T<U...>, V<W...>)
{
return T<U..., W...>();
}
template <template <typename ...> typename T, typename... U, template <typename ...> typename V, typename... W>
constexpr decltype(auto) operator+(T<U...>, V<W...>)
{
return T<U..., W...>();
}
template <template <typename, auto ...> typename T, typename U, auto... V, template <typename, auto ...> typename W, typename X, auto... Y>
constexpr decltype(auto) operator+(T<U, V...>, W<X, Y...>)
{
return T<U, V..., Y...>();
}
template <auto... Args>
struct auto_pack
{
using type = auto_pack<Args...>;
static constexpr size_t value = sizeof...(Args);
static constexpr size_t size() noexcept
{
return value;
}
};
template <typename... Args>
struct type_pack
{
using type = type_pack<Args...>;
static constexpr size_t value = sizeof...(Args);
static constexpr size_t size() noexcept
{
return value;
}
};
template <typename T, auto... Args>
struct args_pack
{
using type = args_pack<T, Args...>;
static constexpr size_t value = sizeof...(Args);
static constexpr size_t size() noexcept
{
return value;
}
};
template <typename T>
struct pack_size : std::integral_constant<size_t, 0>
{
};
template <template <auto ...> typename T, auto... U>
struct pack_size<T<U...>> : std::integral_constant<size_t, sizeof...(U)>
{
};
template <template <typename ...> typename T, typename... U>
struct pack_size<T<U...>> : std::integral_constant<size_t, sizeof...(U)>
{
};
template <template <typename, auto ...> typename T, typename U, auto... V>
struct pack_size<T<U, V...>> : std::integral_constant<size_t, sizeof...(V)>
{
};
template <typename T>
inline constexpr auto pack_size_v = pack_size<T>::value;
template <typename T>
using rank = std::make_index_sequence<pack_size_v<std::decay_t<T>>>;
template <auto m, template <typename, auto ...> typename T, typename U, auto... n>
constexpr decltype(auto) over(T<U, n...>)
{
return type_pack<auto_pack<m, n>...>();
}
template <typename... Args>
constexpr decltype(auto) rank_pack(Args&&... args)
{
return []<auto... N>(std::index_sequence<N...>)
{
return (... + over<N>(rank<Args>()));
}
(std::index_sequence_for<Args...>());
}
template <typename... Args>
constexpr decltype(auto) tuple_cat(Args&&... args)
{
auto t = std::forward_as_tuple(std::forward<Args>(args)...);
if constexpr(!sizeof...(Args))
return t;
else
{
return [&]<template <typename ...> typename T, template <auto ...> typename U, auto... m, auto... n>(T<U<m, n>...>)
{
return std::forward_as_tuple(std::get<n>(std::get<m>(t))...);
}
(rank_pack(std::forward<Args>(args)...));
}
}
template <typename T>
struct is_tuple : std::false_type
{
};
template <typename... Args>
struct is_tuple<std::tuple<Args...>> : std::true_type
{
};
template <typename T>
inline constexpr auto is_tuple_v = is_tuple<T>::value;
template <typename... Args>
using lists = type_pack<Args...>;
}
#endif