8 #ifndef INCLUDE_MOLASSEMBLER_TEMPLE_ALL_PAIRS_ADAPTOR_H
9 #define INCLUDE_MOLASSEMBLER_TEMPLE_ALL_PAIRS_ADAPTOR_H
17 namespace Molassembler {
23 struct EmptySizeSupplier {};
26 struct SingleContainerPairsSizeSupplier {
27 std::size_t size()
const {
28 const std::size_t N =
static_cast<const Base&
>(*this).container.size();
29 return N * (N - 1) / 2;
34 struct TwoContainersPairsSizeSupplier {
35 std::size_t size()
const {
36 const auto& base =
static_cast<const Base&
>(*this);
37 return base.containerT.size() * base.containerU.size();
41 template<
class Container>
42 struct SingleContainerPairsGenerator
43 :
public std::conditional_t<
44 Traits::hasSize<Container>::value,
45 SingleContainerPairsSizeSupplier<SingleContainerPairsGenerator<Container>>,
46 EmptySizeSupplier<SingleContainerPairsGenerator<Container>>
54 using ContainerValueType = decltype(
56 std::declval<const Container>()
60 using PairType = std::pair<ContainerValueType, ContainerValueType>;
62 using ContainerIteratorType = decltype(
63 std::begin(std::declval<const Container>())
69 BoundContainer container;
74 explicit SingleContainerPairsGenerator(
Container&& passContainer)
75 : container(std::forward<Container>(passContainer)) {}
80 template<
class ContainerIterator>
83 using iterator_category = std::forward_iterator_tag;
84 using value_type = PairType;
85 using difference_type = int;
86 using pointer =
const PairType*;
87 using reference =
const PairType&;
90 iterator(ContainerIterator left, ContainerIterator right, ContainerIterator end)
91 : left_(std::move(left)),
92 right_(std::move(right)),
97 iterator& operator ++ () {
109 iterator operator ++ (
int) {
110 iterator prior = *
this;
115 bool operator == (
const iterator& other)
const {
116 return left_ == other.left_ && right_ == other.right_;
119 bool operator != (
const iterator& other)
const {
120 return !(*
this == other);
123 PairType operator * ()
const {
124 return {*left_, *right_};
128 ContainerIterator left_, right_, end_;
131 iterator<ContainerIteratorType> begin()
const {
132 auto maybeNextToBegin = std::begin(container);
133 if(maybeNextToBegin != std::end(container)) {
138 std::begin(container),
139 std::move(maybeNextToBegin),
144 iterator<ContainerIteratorType> end()
const {
145 auto maybePriorToEnd = std::end(container);
146 if(maybePriorToEnd != std::begin(container)) {
151 std::move(maybePriorToEnd),
159 template<
class ContainerT,
class ContainerU>
160 struct TwoContainersAllPairsGenerator
161 :
public std::conditional_t<
162 Traits::hasSize<ContainerT>::value && Traits::hasSize<ContainerU>::value,
163 TwoContainersPairsSizeSupplier<TwoContainersAllPairsGenerator<ContainerT, ContainerU>>,
164 SingleContainerPairsSizeSupplier<TwoContainersAllPairsGenerator<ContainerT, ContainerU>>
169 using BoundContainerT =
typename Binding<ContainerT>::type;
170 using BoundContainerU =
typename Binding<ContainerU>::type;
174 std::declval<ContainerT>()
180 std::declval<ContainerU>()
184 using PairType = std::pair<T, U>;
186 using ContainerTIterator = decltype(
187 std::begin(std::declval<const ContainerT>())
189 using ContainerUIterator = decltype(
190 std::begin(std::declval<const ContainerU>())
196 BoundContainerT containerT;
197 BoundContainerU containerU;
202 TwoContainersAllPairsGenerator(
205 ) : containerT(std::forward<ContainerT>(t)),
206 containerU(std::forward<ContainerU>(u))
212 template<
class TIterator,
class UIterator>
215 using iterator_category = std::forward_iterator_tag;
216 using value_type = PairType;
217 using difference_type = int;
218 using pointer =
const PairType*;
219 using reference =
const PairType&;
221 iterator() =
default;
227 ) : tIter_(std::move(tBegin)),
228 tEnd_(std::move(tEnd)),
229 uBegin_(std::move(uBegin)),
231 uEnd_(std::move(uEnd))
234 iterator& operator ++ () {
236 if(uIter_ == uEnd_) {
244 iterator operator ++ (
int) {
245 iterator prior = *
this;
250 bool operator == (
const iterator& other)
const {
252 std::tie(tIter_, tEnd_, uIter_, uEnd_)
253 == std::tie(other.tIter_, other.tEnd_, other.uIter_, other.uEnd_)
257 bool operator != (
const iterator& other)
const {
258 return !(*
this == other);
261 PairType operator * ()
const {
262 return {*tIter_, *uIter_};
266 TIterator tIter_, tEnd_;
267 UIterator uBegin_, uIter_, uEnd_;
270 iterator<ContainerTIterator, ContainerUIterator> begin()
const {
272 std::begin(containerT),
273 std::end(containerT),
274 std::begin(containerU),
279 iterator<ContainerTIterator, ContainerUIterator> end()
const {
281 std::end(containerT),
282 std::end(containerT),
283 std::begin(containerU),
292 template<
class Container>
294 return Detail::SingleContainerPairsGenerator<Container>(
295 std::forward<Container>(container)
299 template<
class ContainerT,
class ContainerU>
300 auto allPairs(ContainerT&& t, ContainerU&& u) {
301 return Detail::TwoContainersAllPairsGenerator<ContainerT, ContainerU>(
302 std::forward<ContainerT>(t),
303 std::forward<ContainerU>(u)
Provides an identity functor.
Type that will own rvalues, reference lvalues.
Definition: Binding.h:37
Compile-time container type traits.