Audacity 3.2.0
Tuple.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*!********************************************************************
3
4 Audacity: A Digital Audio Editor
5
6 @file Tuple.h
7 @brief Extraction of sub-tuples of std::tuple (or other tuple-like classes)
8
9 Paul Licameli
10
11**********************************************************************/
12#ifndef __AUDACITY_TUPLE__
13#define __AUDACITY_TUPLE__
14
15#include <cstddef>
16#include <tuple>
17#include <type_traits>
18#include <utility>
19
20namespace Tuple {
22template<typename T> struct is_tuple : std::false_type{};
23template<typename... Types> struct is_tuple<std::tuple<Types...>>
24 : std::true_type{};
25template<typename T> static constexpr auto is_tuple_v = is_tuple<T>::value;
26
28template<typename T, typename = void> struct is_tuple_like : std::false_type{};
29template<typename T> struct is_tuple_like<T,
30 // std::tuple_size<T> is only forward-declared except where customized for
31 // T = std::tuple<U...> or other (possibly user) types
32 std::void_t<decltype(std::tuple_size<T>{})>
33>
34 : std::true_type{};
35template<typename T> static constexpr auto is_tuple_like_v =
37
38template<typename Tuple> constexpr bool Empty_v =
39 (0 == size_t(std::tuple_size_v<Tuple>));
40
41template<typename Tuple> [[nodiscard]] constexpr bool Empty(const Tuple &tuple)
42{
43 return Empty_v<Tuple>;
44}
45
46// helpers
47namespace detail {
48template<typename> struct increment_each;
49template<size_t... Indices> struct increment_each<
50 std::index_sequence<Indices...>
51> : std::index_sequence<Indices + 1 ...> {};
52
53template<typename, typename> struct each_less;
54template<size_t... Indices1, size_t... Indices2>
55struct each_less<
56 std::index_sequence<Indices1...>, std::index_sequence<Indices2...>
57> {
58 static constexpr auto value = ((Indices1 < Indices2) && ...);
59};
60
61constexpr size_t npos( -1 );
62
63template<size_t... Indices> struct increasing;
64template<> struct increasing<> { static constexpr auto value = true; };
65template<size_t Index> struct increasing<Index> {
66 static constexpr auto value = true;
67};
68template<size_t Index, size_t... Indices> struct increasing<Index, Indices...> {
69 static constexpr auto value = each_less<
70 std::index_sequence<Index, Indices...>,
71 std::index_sequence<Indices..., npos>
72 >::value;
73};
74}
75
77template<size_t... Indices> constexpr auto Project = [](auto &&tuple)
78{
79 using Tuple = decltype(tuple);
80 constexpr auto size = std::tuple_size_v<std::remove_reference_t<Tuple>>;
81 static_assert(((Indices < size) && ...), "Indices must be in range");
82 // Increasing indices will also be unique, preventing the possibility
83 // of moving-from a tuple member twice
84 // TODO weaker test just for uniqueness
85 static_assert(detail::increasing<Indices...>::value,
86 "Indices must be strictly increasing");
87 return std::make_tuple(std::get<Indices>(std::forward<Tuple>(tuple))...);
88};
89
91template<size_t... Indices, typename Tuple> auto Projection(
92 const std::index_sequence<Indices...> &, Tuple &&tuple)
93{
94 return Project<Indices...>(std::forward<Tuple>(tuple));
95}
96
98template<size_t... Indices> constexpr auto ForwardProject = [](auto &&tuple)
99{
100 using Tuple = decltype(tuple);
101 constexpr auto size = std::tuple_size_v<std::remove_reference_t<Tuple>>;
102 static_assert(((Indices < size) && ...), "Indices must be in range");
103 // Increasing indices will also be unique, preventing the possibility
104 // of (later) moving-from a duplicated rvalue reference in the tuple
105 // TODO weaker test just for uniqueness
106 static_assert(detail::increasing<Indices...>::value,
107 "Indices must be strictly increasing");
108 return
109 std::forward_as_tuple(std::get<Indices>(std::forward<Tuple>(tuple))...);
110};
111
113template<size_t... Indices, typename Tuple> constexpr auto ForwardingProjection(
114 const std::index_sequence<Indices...> &, Tuple &&tuple)
115{
116 return ForwardProject<Indices...>(std::forward<Tuple>(tuple));
117}
118
120template<typename Tuple> auto All(Tuple&& tuple) {
121 constexpr auto Length = std::tuple_size_v<std::decay_t<Tuple>>;
122 return Projection(
123 std::make_index_sequence<Length>{}, std::forward<Tuple>(tuple));
124}
125
127template<typename Tuple> using All_t = decltype(All(std::declval<Tuple>()));
128
130template<typename Tuple> auto ForwardAll(Tuple&& tuple) {
131 constexpr auto Length = std::tuple_size_v<std::decay_t<Tuple>>;
133 std::make_index_sequence<Length>{}, std::forward<Tuple>(tuple));
134}
135
137template<typename Tuple> using ForwardAll_t =
138 decltype(ForwardAll(std::declval<Tuple>()));
139
141template<typename Tuple,
142 typename Decayed = std::decay_t<Tuple>,
143 auto Length = std::tuple_size_v<Decayed>,
144 typename sfinae = std::enable_if_t<(Length > 0)>
145>
146auto Next(Tuple&& tuple) {
147 return Projection(
148 detail::increment_each<std::make_index_sequence<Length - 1>>{},
149 std::forward<Tuple>(tuple));
150}
151
153template<typename Tuple> using Next_t = decltype(Next(std::declval<Tuple>()));
154
156template<typename Tuple,
157 typename Decayed = std::decay_t<Tuple>,
158 auto Length = std::tuple_size_v<Decayed>,
159 typename sfinae = std::enable_if_t<(Length > 0)>
160>
161auto ForwardNext(Tuple&& tuple) {
163 detail::increment_each<std::make_index_sequence<Length - 1>>{},
164 std::forward<Tuple>(tuple));
165}
166
168template<typename Tuple> using ForwardNext_t =
169 decltype(ForwardNext(std::declval<Tuple>()));
170
171}
172
173#endif
constexpr size_t npos(-1)
Definition: Tuple.h:20
decltype(All(std::declval< Tuple >())) All_t
Type of projection of all of a tuple.
Definition: Tuple.h:127
constexpr bool Empty_v
Definition: Tuple.h:38
decltype(Next(std::declval< Tuple >())) Next_t
Type of projection of the tail of a tuple.
Definition: Tuple.h:153
constexpr bool Empty(const Tuple &tuple)
Definition: Tuple.h:41
constexpr auto ForwardProject
Forwarding of a subsequence of a tuple.
Definition: Tuple.h:98
auto Next(Tuple &&tuple)
Projection of the tail of a tuple.
Definition: Tuple.h:146
decltype(ForwardAll(std::declval< Tuple >())) ForwardAll_t
Type of forwarding references to all members of a tuple.
Definition: Tuple.h:138
constexpr auto ForwardingProjection(const std::index_sequence< Indices... > &, Tuple &&tuple)
Destructures a std::index_sequence argument.
Definition: Tuple.h:113
static constexpr auto is_tuple_v
Definition: Tuple.h:25
decltype(ForwardNext(std::declval< Tuple >())) ForwardNext_t
Type of forwarding references to tail members of a tuple.
Definition: Tuple.h:169
auto Projection(const std::index_sequence< Indices... > &, Tuple &&tuple)
Destructures a std::index_sequence argument.
Definition: Tuple.h:91
auto All(Tuple &&tuple)
Projection of all of a tuple.
Definition: Tuple.h:120
static constexpr auto is_tuple_like_v
Definition: Tuple.h:35
auto ForwardNext(Tuple &&tuple)
Forwarding of the tail of a tuple.
Definition: Tuple.h:161
auto ForwardAll(Tuple &&tuple)
Forwarding of all of a tuple.
Definition: Tuple.h:130
constexpr auto Project
Return a tuple of values initialized from a subsequence of a tuple.
Definition: Tuple.h:77
STL namespace.
Type test metapredicate, for more general tuple-like types.
Definition: Tuple.h:28
Type test metapredicate, for specializations of std::tuple only.
Definition: Tuple.h:22