diff --git a/STL_Extension/doc_tex/STL_Extension_ref/stl_extension.tex b/STL_Extension/doc_tex/STL_Extension_ref/stl_extension.tex index f085905948b..4de0741fdb3 100644 --- a/STL_Extension/doc_tex/STL_Extension_ref/stl_extension.tex +++ b/STL_Extension/doc_tex/STL_Extension_ref/stl_extension.tex @@ -203,8 +203,14 @@ \ccCreationVariable{i} \ccDefinition The class \ccClassTemplateName\ defines an - \ccc{OutputIterator} that contains a tuple of output iterators, and dispatches - among those based on the type of the value type which is put in it. + \ccc{OutputIterator} that contains a tuple of output iterators, and + dispatches among those based on the type of the value type which is + put in it. Besides defining assignment for all parameters of V it is + also defined for the types \ccStyle{boost::variant} and + \ccStyle{boost::optional>}, where T\ldots\ + must be a subset of the parameters of \ccc{V}. Should the + \ccStyle{boost::optional} be empty, it will be discarded. + It also inherits from \ccc{O}, which makes it easy to treat like a tuple. \ccParameters @@ -249,10 +255,17 @@ \ccCreationVariable{i} \ccDefinition The class \ccClassTemplateName\ defines an - \ccc{OutputIterator} that contains a tuple of output iterators, and dispatches - among those based on the type of the value type which is put in it. - Other types are also accepted, and the object is simply discarded in this case. - It also inherits from \ccc{O}, which makes it easy to treat like a tuple. + \ccc{OutputIterator} that contains a tuple of output iterators, and + dispatches among those based on the type of the value type which is + put in it. Other types are also accepted, and the object is simply + discarded in this case. Besides defining assignment for all + parameters of V it is also defined for the types + \ccStyle{boost::variant} and + \ccStyle{boost::optional>}, where T\ldots\ + can be a list of arbitrary types. + + It also inherits from \ccc{O}, which makes it easy to treat like a + tuple. \ccParameters \ccc{V} must be a \ccc{CGAL::cpp0x::tuple<...>} of the types of values to be accepted and dispatched. diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index 729114c11d6..985ba056aa1 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include #if defined(BOOST_MSVC) # pragma warning(push) @@ -1182,6 +1184,22 @@ inline Filter_output_iterator< I, P > filter_output_iterator(I e, const P& p) { return Filter_output_iterator< I, P >(e, p); } +namespace internal { + +template +struct Output_visitor : boost::static_visitor { + Output_visitor(OutputIterator* it) : out(it) {} + OutputIterator* out; + + template + OutputIterator& operator()(const T& t) { + *(*out)++ = t; + return *out; + } +}; + +} // internal + #ifndef CGAL_CFG_NO_CPP0X_VARIADIC_TEMPLATES @@ -1215,6 +1233,7 @@ struct Derivator, cpp0x::tuple > return static_cast(*this); } }; +}; } // internal @@ -1265,6 +1284,20 @@ public: return *this; } + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } + Self& operator++() { return *this; } Self& operator++(int) { return *this; } Self& operator*() { return *this; } @@ -1365,6 +1398,20 @@ public: static_cast< Iterator_tuple& >(*this) = static_cast< const Iterator_tuple& >(s); return *this; } + + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } const Iterator_tuple& get_iterator_tuple() const { return *this; } @@ -1467,6 +1514,20 @@ public: return *this; } + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } + const Iterator_tuple& get_iterator_tuple() const { return *this; } @@ -1578,6 +1639,20 @@ public: return *this; } + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } + const Iterator_tuple& get_iterator_tuple() const { return *this; } @@ -1701,7 +1776,21 @@ public: static_cast< Iterator_tuple& >(*this) = static_cast< const Iterator_tuple& >(s); return *this; } - + + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } + const Iterator_tuple& get_iterator_tuple() const { return *this; } @@ -1836,6 +1925,21 @@ public: return *this; } + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } + + const Iterator_tuple& get_iterator_tuple() const { return *this; } @@ -1980,6 +2084,20 @@ public: return *this; } + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } + const Iterator_tuple& get_iterator_tuple() const { return *this; } @@ -2134,6 +2252,20 @@ public: return *this; } + template + Self& operator=(const boost::variant& t) { + internal::Output_visitor visitor(this); + boost::apply_visitor(visitor, t); + return *this; + } + + template + Self& operator=(const boost::optional< boost::variant >& t) { + internal::Output_visitor visitor(this); + if(t) boost::apply_visitor(visitor, *t); + return *this; + } + const Iterator_tuple& get_iterator_tuple() const { return *this; } diff --git a/STL_Extension/test/STL_Extension/test_dispatch_output.cpp b/STL_Extension/test/STL_Extension/test_dispatch_output.cpp index ac92d3d4db6..6bddafeda07 100644 --- a/STL_Extension/test/STL_Extension/test_dispatch_output.cpp +++ b/STL_Extension/test/STL_Extension/test_dispatch_output.cpp @@ -6,6 +6,9 @@ #include +#include +#include + struct A{}; struct B{}; @@ -76,6 +79,47 @@ void complete_test(std::vector data1,std::list data2){ CGAL::cpp0x::tie(d, bck_ins) = drop; } +void variant_test() { + typedef boost::variant var; + typedef boost::optional< var > ovar; + std::vector a; + std::vector b; + std::vector c; + typedef CGAL::Dispatch_output_iterator< + CGAL::cpp0x::tuple, + CGAL::cpp0x::tuple >, + std::back_insert_iterator< std::vector >, + std::back_insert_iterator< std::vector > + > > Dispatch; + Dispatch disp = CGAL::dispatch_output(std::back_inserter(a), + std::back_inserter(b), + std::back_inserter(c)); + { + var va = 23; var vb = 4.2; var vc = 'x'; + *disp++ = va; *disp++ = vb; *disp++ = vc; *disp++ = 42; + } + assert(a.size() == 2); + assert(a.front() == 23); + assert(a.back() == 42); + assert(b.size() == 1); + assert(b.front() == 4.2); + assert(c.size() == 1); + assert(c.front() == 'x'); + a.clear(); b.clear(); c.clear(); + + { + ovar va = var(23); ovar vb = var(4.2); ovar vc = var('x'); + *disp++ = va; *disp++ = vb; *disp++ = vc; *disp++ = 42; *disp++ = ovar(); + } + assert(a.size() == 2); + assert(a.front() == 23); + assert(a.back() == 42); + assert(b.size() == 1); + assert(b.front() == 4.2); + assert(c.size() == 1); + assert(c.front() == 'x'); +} + int main(){ std::list list1; @@ -93,5 +137,7 @@ int main(){ complete_test(vect2,list1); complete_test(vect2,list2); + variant_test(); + return 0; }