Skip to content

C++17 implementation of Dispatch_(or_drop)?_output_iterator #8854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 73 additions & 109 deletions STL_Extension/include/CGAL/iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -1282,98 +1282,98 @@ struct Output_visitor {

} // internal

namespace tuple_internal {
template <typename ...Args, std::size_t ...Is>
auto to_tuple(std::tuple<Args...> &t, std::index_sequence<Is...>)
{
return std::tuple<Args&...>(std::get<Is>(t)...);
}

}//end namespace tuple_internal

namespace internal {
// OutputIterator which accepts several types in *o++= and dispatches,
// wraps several other output iterators, and dispatches accordingly.
template < typename V, typename O, bool or_drop = false >
class Dispatch_output_iterator;

template < typename D, typename V = std::tuple<>, typename O = std::tuple<> >
struct Derivator
{
typedef Derivator<D, V, O> Self;
Derivator() = default;
Derivator(const Self&) = default;
Self& operator=(const Self&) = delete;
template <class Tuple>
void tuple_dispatch(const Tuple&)
{}
template <std::size_t N, typename V, typename O>
struct Output_to_nth_of_tuple_of_iterators {
template <typename Tuple>
static void assign(Tuple& tuple, const V& v) {
*std::get<N>(tuple)++ = v;
}
};

template < typename D, typename V1, typename O1, typename... V, typename... O>
struct Derivator<D, std::tuple<V1, V...>, std::tuple<O1, O...> >
: public Derivator<D, std::tuple<V...>, std::tuple<O...> >
template <bool drop_value>
struct Drop_output_iterator
{
typedef Derivator<D, std::tuple<V1, V...>, std::tuple<O1, O...> > Self;
typedef Derivator<D, std::tuple<V...>, std::tuple<O...> > Base;

Derivator() = default;
Derivator(const Self&) = default;
Self& operator=(const Self&) = delete;

using Base::operator=;

D& operator=(const V1& v)
{
* std::get< D::size - sizeof...(V) - 1 >(static_cast<typename D::Iterator_tuple&>(static_cast<D&>(*this))) ++ = v;
return static_cast<D&>(*this);
template <typename Tuple, typename T>
static void assign(Tuple&, const T&) {
// Drop the value... Only if `drop_value==true`.
}
};

template <class Tuple>
void tuple_dispatch(const Tuple& t)
{
* std::get< D::size - sizeof...(V) - 1 >(static_cast<typename D::Iterator_tuple&>(static_cast<D&>(*this))) ++ =
std::get< D::size - sizeof...(V) - 1 >(t);
static_cast<Base&>(*this).tuple_dispatch(t);
}
template <>
struct Drop_output_iterator<false>
{
// fake assign, declared but not defined
template <typename Tuple>
static void assign(Tuple& tuple, Null_tag);
};

} // internal
template <typename Values, typename OutputIterators, typename Indices, bool>
struct Dispatch_output_iterator_aux;

namespace tuple_internal {
template <typename ...Args, std::size_t ...Is>
auto to_tuple(std::tuple<Args...> &t, std::index_sequence<Is...>)
template <typename... V, typename... O, std::size_t... Indices, bool drop_unknown_value_types>
struct Dispatch_output_iterator_aux<std::tuple<V...>,
std::tuple<O...>,
std::index_sequence<Indices...>,
drop_unknown_value_types>
: public Output_to_nth_of_tuple_of_iterators<Indices, V, O>...,
public Drop_output_iterator<drop_unknown_value_types>
{
return std::tuple<Args&...>(std::get<Is>(t)...);
}
using Output_to_nth_of_tuple_of_iterators<Indices, V, O>::assign...;
using Drop_output_iterator<drop_unknown_value_types>::assign;

}//end namespace tuple_internal

// OutputIterator which accepts several types in *o++= and dispatches,
// wraps several other output iterators, and dispatches accordingly.
template < typename V, typename O >
class Dispatch_output_iterator;
template <typename Tuple>
void tuple_dispatch(const Tuple& t) {
// Assign each element of the tuple to the corresponding output iterator,
// using a fold expression on "operator," to expand the parameter pack.
( static_cast<Output_to_nth_of_tuple_of_iterators<Indices, V, O>&>(*this).
assign(*this, std::get<Indices>(t)), ...);
}
};

template < typename... V, typename... O >
class Dispatch_output_iterator < std::tuple<V...>, std::tuple<O...> >
: private internal::Derivator<Dispatch_output_iterator< std::tuple<V...>, std::tuple<O...> >, std::tuple<V...>, std::tuple<O...> >
, public std::tuple<O...>
template < typename... V, typename... O, bool drop_unknown_value_types >
class Dispatch_output_iterator < std::tuple<V...>, std::tuple<O...>, drop_unknown_value_types >
: public Dispatch_output_iterator_aux< std::tuple<V...>, std::tuple<O...>,
std::make_index_sequence<sizeof...(O)>, drop_unknown_value_types >
, public std::tuple<O...>
{
static_assert(sizeof...(V) == sizeof...(O),
"The number of explicit template parameters has to match the number of arguments");

static const int size = sizeof...(V);

template <typename D, typename V_, typename O_>
friend struct internal::Derivator;

public:
using Iterator_tuple = std::tuple<O...>;
using Value_type_tuple = std::tuple<V...>;

typedef std::tuple<O...> Iterator_tuple;
typedef std::tuple<V...> Value_type_tuple;

typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
using iterator_category = std::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;

private:

typedef Dispatch_output_iterator Self;
typedef internal::Derivator<Self, Value_type_tuple, Iterator_tuple > Base;
using Self = Dispatch_output_iterator;
using Base = Dispatch_output_iterator_aux<std::tuple<V...>,
std::tuple<O...>,
std::index_sequence_for<O...>,
drop_unknown_value_types>;

public:

using Base::operator=;
using Base::tuple_dispatch;

Dispatch_output_iterator(O... o) : std::tuple<O...>(o...) {}
Expand All @@ -1387,6 +1387,12 @@ class Dispatch_output_iterator < std::tuple<V...>, std::tuple<O...> >
return *this;
}

template <typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, Self>>>
Self& operator=(const T& t) {
this->assign(*this, t);
return *this;
}

template<typename ... T>
Self& operator=(const std::variant< T ... >& t) {
internal::Output_visitor<Self> visitor(this);
Expand Down Expand Up @@ -1435,50 +1441,8 @@ dispatch_output(O... o)
// Same as Dispatch_output_iterator, but has a dummy *o++= for all other types
// that drops the data (same as Emptyset_iterator).

template < typename V, typename O >
class Dispatch_or_drop_output_iterator;

template < typename... V, typename... O >
class Dispatch_or_drop_output_iterator < std::tuple<V...>, std::tuple<O...> >
: public Dispatch_output_iterator< std::tuple<V...>, std::tuple<O...> >
{
typedef Dispatch_or_drop_output_iterator Self;
typedef Dispatch_output_iterator< std::tuple<V...>, std::tuple<O...> > Base;

template <typename D, typename V_, typename O_>
friend struct internal::Derivator;

public:

Dispatch_or_drop_output_iterator(O... o) : Base(o...) {}

Dispatch_or_drop_output_iterator(const Dispatch_or_drop_output_iterator&)=default;
Dispatch_or_drop_output_iterator& operator=(const Dispatch_or_drop_output_iterator&)=default;

using Base::operator=;

Self& operator*() { return *this; }
Self& operator++() { return *this; }
Self& operator++(int) { return *this; }

template <class T>
Self& operator=(const T&) { return *this; }

template<typename ... T>
Self& operator=(const std::variant< T ... >& t) {
internal::Output_visitor<Self> visitor(this);
std::visit(visitor, t);
return *this;
}

template<typename ... T>
Self& operator=(const std::optional< std::variant< T ... > >& t) {
internal::Output_visitor<Self> visitor(this);
if(t) std::visit(visitor, *t);
return *this;
}
};

template < typename Tuple_of_v, typename Tuple_of_output_it >
using Dispatch_or_drop_output_iterator = Dispatch_output_iterator< Tuple_of_v, Tuple_of_output_it, true >;

template < typename... V, typename... O>
inline
Expand Down