1 /* Copyright (c) 2004-2023 The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #ifndef XBT_UTILS_ITER_ITERATOR_WRAPPING_HPP
7 #define XBT_UTILS_ITER_ITERATOR_WRAPPING_HPP
10 #include <type_traits>
12 namespace simgrid::xbt {
14 template <typename T> struct ref_or_value {
15 using type = std::conditional_t<std::is_lvalue_reference<T>::value,
16 std::reference_wrapper<typename std::remove_reference<T>::type>, T>;
18 template <typename T> using ref_or_value_t = typename ref_or_value<T>::type;
21 * @brief A container which simply forwards its arguments to an
22 * iterator to begin traversal over another collection
24 * An `iterator_wrapping` acts as a proxy to the collection that it
25 * wraps. You create an `iterator_wrapping` as a convenience to needing
26 * to manually check stop and end conditions when constructing iterators
27 * directly, e.g. in a for-loop. With an `iterator_wrapping`, you can
28 * simply act as if the iterator were a collection and use it e.g. in
29 * auto-based for-loops.
31 * @class Iterator: The type of the iterator that is constructed to
32 * traverse the container.
34 * @note The wrapping only works correctly if the iterator type (Iterator)
35 * that is constructed can be default constructed, and only if the default-constructed
36 * iterate is a valid representation of the "end()" of any iterator type.
37 * That is, if you must supply additional arguments to indicate the end of a collection,
38 * you'll have to construct is manually.
40 template <typename Iterator, typename... Args> struct iterator_wrapping {
42 std::tuple<ref_or_value_t<Args>...> m_args;
44 template <typename IteratorType, typename... Arguments>
45 friend constexpr iterator_wrapping<IteratorType, Arguments...> make_iterator_wrapping(Arguments&&... args);
47 template <typename IteratorType, typename... Arguments>
48 friend constexpr iterator_wrapping<IteratorType, Arguments...> make_iterator_wrapping_explicit(Arguments... args);
51 iterator_wrapping(Args&&... begin_iteration) : m_args(ref_or_value_t<Args>(begin_iteration)...) {}
52 iterator_wrapping(const iterator_wrapping&) = delete;
53 iterator_wrapping(iterator_wrapping&&) = delete;
54 iterator_wrapping& operator=(const iterator_wrapping&) = delete;
55 iterator_wrapping& operator=(iterator_wrapping&&) = delete;
57 Iterator begin() const
59 return std::apply([](auto&... args) { return Iterator(args...); }, m_args);
61 Iterator end() const { return Iterator(); }
64 template <typename Iterator, typename... Args>
65 constexpr iterator_wrapping<Iterator, Args...> make_iterator_wrapping(Args&&... args)
67 return iterator_wrapping<Iterator, Args...>(std::forward<Args>(args)...);
70 template <typename Iterator, typename... Args>
71 constexpr iterator_wrapping<Iterator, Args...> make_iterator_wrapping_explicit(Args... args)
73 return iterator_wrapping<Iterator, Args...>(args...);
76 } // namespace simgrid::xbt