forked from ericniebler/stl2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtagged.tex
122 lines (112 loc) · 4.16 KB
/
tagged.tex
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
%!TEX root = stl2-ts.tex
\infannex{tagged}{Reference implementation for \tcode{tagged}}
\pnum Below is a reference implementation of the \tcode{tagged} class template described in
\ref{taggedtup.tagged}, and also \tcode{tagged_pair}~(\ref{tagged.pairs}),
\tcode{tagged_tuple}~(\ref{tagged.tuple}), and \tcode{tag::in}~(\ref{alg.tagspec}).
\begin{codeblock}
namespace std { @\newtxt{namespace experimental \{ namespace ranges_v1 \{}@
template <class Base, class...Tags>
struct tagged;
template <class Base, class...Tags>
struct tuple_size<tagged<Base, Tags...>>
: tuple_size<Base> { };
template <size_t N, class Base, class...Tags>
struct tuple_element<N, tagged<Base, Tags...>>
: tuple_element<N, Base> { };
struct __getters {
private:
template <class, class...> friend struct tagged;
template <class Type, class Indices, class...Tags>
struct collect_;
template <class Type, std::size_t...Is, class...Tags>
struct collect_<Type, index_sequence<Is...>, Tags...>
: Tags::template getter<Type, Is>... {
collect_() = default;
collect_(const collect_&) = default;
collect_& operator=(const collect_&) = default;
private:
template <class, class...> friend struct tagged;
~collect_() = default;
};
template <class Type, class...Tags>
using collect = collect_<Type, make_index_sequence<sizeof...(Tags)>, Tags...>;
};
template <class Base, class...Tags>
struct tagged
: Base, __getters::collect<tagged<Base, Tags...>, Tags...> {
using Base::Base;
tagged() = default;
tagged(tagged&&) = default;
tagged(const tagged&) = default;
tagged &operator=(tagged&&) = default;
tagged &operator=(const tagged&) = default;
template <typename Other>
requires Constructible<Base, Other>@\newtxt{()}@
tagged(tagged<Other, Tags...> &&that)
: Base(static_cast<Other &&>(that)) { }
template <typename Other>
requires Constructible<Base, const Other&>@\newtxt{()}@
tagged(tagged<Other, Tags...> const &that)
: Base(static_cast<const Other&>(that)) { }
template <typename Other>
requires Assignable<Base@\newtxt{\&}@, Other>@\newtxt{()}@
tagged& operator=(tagged<Other, Tags...>&& that) {
static_cast<Base&>(*this) = static_cast<Other&&>(that);
return *this;
}
template <typename Other>
requires Assignable<Base@\newtxt{\&}@, const Other&>@\newtxt{()}@
tagged& operator=(const tagged<Other, Tags...>& that) {
static_cast<Base&>(*this) = static_cast<const Other&>(that);
return *this;
}
template <class U>
requires Assignable<Base@\newtxt{\&}@, U>@\newtxt{()}@ && !Same<decay_t<U>, tagged>@\newtxt{()}@
tagged& operator=(U&& u) {
static_cast<Base&>(*this) = std::forward<U>(u);
return *this;
}
};
template <class T>
struct __tag_spec { };
template <class Spec, class Arg>
struct __tag_spec<Spec(Arg)> { using type = Spec; };
template <class T>
struct __tag_elem { };
template <class Spec, class Arg>
struct __tag_elem<Spec(Arg)> { using type = Arg; };
template <class F, class S>
using tagged_pair =
tagged<pair<typename __tag_elem<F>::type, typename __tag_elem<S>::type>,
typename __tag_spec<F>::type, typename __tag_spec<S>::type>;
template <class...Types>
using tagged_tuple =
tagged<tuple<typename __tag_elem<Types>::type...>,
typename __tag_spec<Types>::type...>;
namespace tag {
struct in {
private:
friend struct __getters;
template <class Derived, size_t I>
struct getter {
getter() = default;
getter(const getter&) = default;
getter &operator=(const getter&) = default;
constexpr decltype(auto) in() & {
return get<I>(static_cast<Derived &>(*this));
}
constexpr decltype(auto) in() && {
return get<I>(static_cast<Derived &&>(*this));
}
constexpr decltype(auto) in() const & {
return get<I>(static_cast<const Derived &>(*this));
}
private:
friend struct __getters;
~getter() = default;
};
}
// Other tag specifiers defined similarly, see \ref{alg.tagspec}
}
}@\newtxt{\}\}}@
\end{codeblock}