From 5db3ed8134d94ed528f5de557b875ac6a6885914 Mon Sep 17 00:00:00 2001 From: denzor200 Date: Sat, 6 Nov 2021 20:09:19 +0400 Subject: [PATCH 1/2] [transform_view_ext] Updated docs --- doc/iterator.qbk | 1 + doc/sequence.qbk | 1 + doc/view.qbk | 15 ++++++--------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/doc/iterator.qbk b/doc/iterator.qbk index ef33240a..51640450 100644 --- a/doc/iterator.qbk +++ b/doc/iterator.qbk @@ -254,6 +254,7 @@ expressions must be valid: * __iterator_range__ iterator (where adapted iterators are __associative_iterator__\ s) * __joint_view__ iterator (where adapted sequences are __associative_sequence__\ s and __forward_sequence__\ s) * __reverse_view__ iterator (where adapted sequence is an __associative_sequence__ and a __bidirectional_sequence__) +* __transform_view__ iterator (where adapted sequence is an __associative_sequence__ and a __forward_sequence__) [endsect] diff --git a/doc/sequence.qbk b/doc/sequence.qbk index 6f50fe21..b193b8e9 100644 --- a/doc/sequence.qbk +++ b/doc/sequence.qbk @@ -360,6 +360,7 @@ you can use `__result_of_value_at_key__`.] * __iterator_range__ (where adapted iterators are __associative_iterator__\ s) * __joint_view__ (where adapted sequences are __associative_sequence__\ s and __forward_sequence__\ s) * __reverse_view__ (where adapted sequence is an __associative_sequence__ and a __bidirectional_sequence__) +* __transform_view__ (where adapted sequence is an __associative_sequence__ and a __forward_sequence__) [endsect] diff --git a/doc/view.qbk b/doc/view.qbk index f39fb7fa..6caa33fc 100644 --- a/doc/view.qbk +++ b/doc/view.qbk @@ -328,9 +328,7 @@ defined in __forward_sequence__. The unary version of `transform_view` presents a view of its underlying sequence given a unary function object or function pointer. The binary version of `transform_view` presents a view of 2 underlying sequences, -given a binary function object or function pointer. The `transform_view` -inherits the traversal characteristics (see __traversal_concept__) of -its underlying sequence or sequences. +given a binary function object or function pointer. [heading Header] @@ -362,9 +360,10 @@ its underlying sequence or sequences. [heading Model of] -* __forward_sequence__, __bidirectional_sequence__ or -__random_access_sequence__ depending on the traversal characteristics (see -__traversal_concept__) of its underlying sequence. +* A model of __forward_sequence__ if `Sequence` is a __forward_sequence__ +else, __bidirectional_sequence__ if `Sequence` is a __bidirectional_sequence__ +else, __random_access_sequence__ if `Sequence` is a __random_access_sequence__. +* __associative_sequence__ if `Sequence` implements the __associative_sequence__ model. [variablelist Notation [[`TV`] [A `transform_view` type]] @@ -381,9 +380,7 @@ __traversal_concept__) of its underlying sequence. [heading Expression Semantics] Semantics of an expression is defined only where it differs from, or is not -defined in __forward_sequence__, __bidirectional_sequence__ or -__random_access_sequence__ depending on the traversal characteristics (see -__traversal_concept__) of its underlying sequence or sequences. +defined in the implemented models. [table [[Expression] [Semantics]] From a57683a68d24cbaab9df5f2edc6c77d63f6587a3 Mon Sep 17 00:00:00 2001 From: denzor200 Date: Sun, 9 Jan 2022 16:34:07 +0400 Subject: [PATCH 2/2] [transform_view_ext] Unary transform_view is an Associative Sequence now --- doc/view.qbk | 1 + .../transform_view/detail/deref_data_impl.hpp | 66 +++++ .../transform_view/detail/key_of_impl.hpp | 47 +++ .../detail/value_of_data_impl.hpp | 47 +++ .../transform_view_iterator.hpp | 3 + test/sequence/transform_view.cpp | 273 ++++++++++++++++++ 6 files changed, 437 insertions(+) create mode 100644 include/boost/fusion/view/transform_view/detail/deref_data_impl.hpp create mode 100644 include/boost/fusion/view/transform_view/detail/key_of_impl.hpp create mode 100644 include/boost/fusion/view/transform_view/detail/value_of_data_impl.hpp diff --git a/doc/view.qbk b/doc/view.qbk index e65ac630..d99b325f 100644 --- a/doc/view.qbk +++ b/doc/view.qbk @@ -363,6 +363,7 @@ given a binary function object or function pointer. * __forward_sequence__, __bidirectional_sequence__ or __random_access_sequence__ depending on the traversal characteristics (see __traversal_concept__) of its underlying sequence or sequences. +* __associative_sequence__ if underlying sequence implements the __associative_sequence__ model(available only with unary version of `transform_view`). [variablelist Notation [[`TV`] [A `transform_view` type]] diff --git a/include/boost/fusion/view/transform_view/detail/deref_data_impl.hpp b/include/boost/fusion/view/transform_view/detail/deref_data_impl.hpp new file mode 100644 index 00000000..3eb325a4 --- /dev/null +++ b/include/boost/fusion/view/transform_view/detail/deref_data_impl.hpp @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (c) 2022 Denis Mikhailov + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_FUSION_TRANSFORM_VIEW_DEREF_DATA_IMPL_JAN_9_2022_0354PM) +#define BOOST_FUSION_TRANSFORM_VIEW_DEREF_DATA_IMPL_JAN_9_2022_0354PM + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + namespace extension + { + template + struct deref_data_impl; + + // Unary Version + template<> + struct deref_data_impl + { + template + struct apply + { + typedef typename + result_of::deref::type + value_type; + + typedef typename Iterator::transform_type F; + typedef typename boost::result_of::type transformed_type; + typedef typename boost::remove_reference::type transformed_type_unref; + typedef typename boost::remove_const::type transformed_type_unconst; + + typedef typename transformed_type_unconst::second_type raw_type; + typedef typename + boost::mpl::if_< + is_reference + , typename boost::mpl::if_< + is_const + , typename boost::add_reference::type>::type + , typename boost::add_reference::type + >::type + , raw_type + >::type + type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + static type + call(Iterator const& i) + { + return i.f(fusion::deref(i.first)).second; + } + }; + }; + + // Binary Version is not supported with Associative Sequence + } +}} + +#endif diff --git a/include/boost/fusion/view/transform_view/detail/key_of_impl.hpp b/include/boost/fusion/view/transform_view/detail/key_of_impl.hpp new file mode 100644 index 00000000..226814f1 --- /dev/null +++ b/include/boost/fusion/view/transform_view/detail/key_of_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2022 Denis Mikhailov + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_FUSION_TRANSFORM_VIEW_KEY_OF_IMPL_JAN_9_2022_0354PM) +#define BOOST_FUSION_TRANSFORM_VIEW_KEY_OF_IMPL_JAN_9_2022_0354PM + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + namespace extension + { + template + struct key_of_impl; + + // Unary Version + template<> + struct key_of_impl + { + template + struct apply + { + typedef typename + result_of::deref::type + value_type; + + typedef typename Iterator::transform_type F; + typedef typename boost::result_of::type transformed_type; + typedef typename boost::remove_reference::type transformed_type_unref; + typedef typename boost::remove_const::type transformed_type_unconst; + + typedef typename transformed_type_unconst::first_type type; + }; + }; + + // Binary Version is not supported with Associative Sequence + } +}} +#endif diff --git a/include/boost/fusion/view/transform_view/detail/value_of_data_impl.hpp b/include/boost/fusion/view/transform_view/detail/value_of_data_impl.hpp new file mode 100644 index 00000000..e350db49 --- /dev/null +++ b/include/boost/fusion/view/transform_view/detail/value_of_data_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2022 Denis Mikhailov + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ + +#if !defined(BOOST_FUSION_TRANSFORM_VIEW_VALUE_OF_IMPL_JAN_9_2022_0354PM) +#define BOOST_FUSION_TRANSFORM_VIEW_VALUE_OF_IMPL_JAN_9_2022_0354PM + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + namespace extension + { + template + struct value_of_data_impl; + + // Unary Version + template<> + struct value_of_data_impl + { + template + struct apply + { + typedef typename + result_of::deref::type + value_type; + + typedef typename Iterator::transform_type F; + typedef typename boost::result_of::type transformed_type; + typedef typename boost::remove_reference::type transformed_type_unref; + typedef typename boost::remove_const::type transformed_type_unconst; + + typedef typename transformed_type_unconst::second_type type; + }; + }; + + // Binary Version is not supported with Associative Sequence + } +}} +#endif diff --git a/include/boost/fusion/view/transform_view/transform_view_iterator.hpp b/include/boost/fusion/view/transform_view/transform_view_iterator.hpp index 2689ae8a..071cba8e 100644 --- a/include/boost/fusion/view/transform_view/transform_view_iterator.hpp +++ b/include/boost/fusion/view/transform_view/transform_view_iterator.hpp @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include namespace boost { namespace fusion { diff --git a/test/sequence/transform_view.cpp b/test/sequence/transform_view.cpp index b9e3f943..4f11e6b7 100644 --- a/test/sequence/transform_view.cpp +++ b/test/sequence/transform_view.cpp @@ -1,11 +1,14 @@ /*============================================================================= Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2022 Denis Mikhailov Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #include #include +#include +#include #include #include #include @@ -14,15 +17,29 @@ #include #include #include +#include +#include +#include +#include #include #include #include #include #include +#include +#include +#include +#include +#include #include #include +#include +#include #include +#include +#include +#include struct square { @@ -60,6 +77,85 @@ struct add } }; +struct abstract +{ + virtual void foo() = 0; +}; + +struct functor +{ + typedef boost::fusion::pair pair_0; + typedef boost::fusion::pair pair_1; + typedef boost::fusion::pair pair_2; + + typedef boost::mpl::map< + boost::mpl::pair< boost::fusion::pair , pair_0> + , boost::mpl::pair< pair_1 , pair_1> + , boost::mpl::pair< boost::fusion::pair , pair_2> + > m; + + template + struct result; + + template + struct result + : boost::mpl::at< + m, + typename boost::remove_reference::type + > + {}; + + pair_0 operator() (const boost::fusion::pair& arg) const + { + return pair_0(arg.second); + } + + pair_1 operator() (const pair_1 & arg) const + { + return pair_1(arg.second + "_transformed"); + } + + pair_2 operator() (const boost::fusion::pair& arg) const + { + return pair_2(arg.second); + } +}; + +struct simple_identity +{ + template + struct result; + + template + struct result + { + typedef U type; + }; + + template + T& operator() (T& arg) const + { + return arg; + } +}; + +struct simple_identity_nonref +{ + template + struct result; + + template + struct result + : boost::remove_reference + {}; + + template + T operator() (T arg) const + { + return arg; + } +}; + int main() { @@ -110,6 +206,183 @@ main() BOOST_MPL_ASSERT((boost::is_same::type, int>)); } + /// Associative + { + typedef map< + pair + , pair + , pair > + map_type; + typedef transform_view transformed_type; + + BOOST_MPL_ASSERT((traits::is_associative)); + BOOST_MPL_ASSERT((traits::is_random_access)); + + map_type m( + make_pair('X') + , make_pair("Men") + , make_pair(2)); + transformed_type t(m, functor()); + + std::cout << at_key(t) << std::endl; + std::cout << at_key(t) << std::endl; + std::cout << at_key(t) << std::endl; + + BOOST_TEST(at_key(t) == 'X'); + BOOST_TEST(at_key(t) == "Men_transformed"); + BOOST_TEST(at_key(t) == 2); + + BOOST_STATIC_ASSERT(( + boost::is_same::type, char>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::type, std::string>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::type, long>::value)); + + std::cout << t << std::endl; + + BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); + BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); + BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); + BOOST_STATIC_ASSERT((!boost::fusion::result_of::has_key::value)); + + std::cout << deref_data(begin(t)) << std::endl; + std::cout << deref_data(boost::fusion::next(begin(t))) << std::endl; + + BOOST_TEST(deref_data(begin(t)) == 'X'); + BOOST_TEST(deref_data(boost::fusion::next(begin(t))) == "Men_transformed"); + BOOST_TEST(deref_data(boost::fusion::next(next(begin(t)))) == 2); + + BOOST_STATIC_ASSERT((boost::is_same::type>::type, short>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, double>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, abstract>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type, char>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, std::string>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, long>::value)); + + // Test random access interface. + pair a = at_c<0>(t); (void) a; + pair b = at_c<1>(t); + pair c = at_c<2>(t); + (void)c; + + typedef boost::fusion::result_of::begin::type first; + typedef boost::fusion::result_of::next::type second; + typedef boost::fusion::result_of::next::type third; + + BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); + BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); + BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); + } + + { + typedef map< + pair + , pair + , pair > + map_type; + typedef transform_view transformed_type; + + BOOST_MPL_ASSERT((traits::is_associative)); + BOOST_MPL_ASSERT((traits::is_random_access)); + + map_type m( + make_pair('X') + , make_pair("Men") + , make_pair(2)); + transformed_type t(m, simple_identity()); + + std::cout << at_key(t) << std::endl; + std::cout << at_key(t) << std::endl; + std::cout << at_key(t) << std::endl; + + BOOST_TEST(at_key(t) == 'X'); + BOOST_TEST(at_key(t) == "Men"); + BOOST_TEST(at_key(t) == 2); + + BOOST_STATIC_ASSERT(( + boost::is_same::type, char>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::type, std::string>::value)); + BOOST_STATIC_ASSERT(( + boost::is_same::type, int>::value)); + + std::cout << t << std::endl; + + BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); + BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); + BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); + BOOST_STATIC_ASSERT((!boost::fusion::result_of::has_key::value)); + + std::cout << deref_data(begin(t)) << std::endl; + std::cout << deref_data(boost::fusion::next(begin(t))) << std::endl; + + BOOST_TEST(deref_data(begin(t)) == 'X'); + BOOST_TEST(deref_data(boost::fusion::next(begin(t))) == "Men"); + BOOST_TEST(deref_data(boost::fusion::next(next(begin(t)))) == 2); + + BOOST_STATIC_ASSERT((boost::is_same::type>::type, int>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, double>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, abstract>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type, char>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, std::string>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, int>::value)); + + // Test random access interface. + pair a = at_c<0>(t); (void) a; + pair b = at_c<1>(t); + pair c = at_c<2>(t); + (void)c; + + typedef boost::fusion::result_of::begin::type first; + typedef boost::fusion::result_of::next::type second; + typedef boost::fusion::result_of::next::type third; + + // BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); + // BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); + // BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); + } + + { + // compile test only + // make sure result_of::deref_data returns a reference + typedef map > map_type; + typedef transform_view transformed_type; + typedef boost::fusion::result_of::begin::type i_type; + typedef boost::fusion::result_of::deref_data::type r_type; + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + // compile test only + // make sure result_of::deref_data is const correct + typedef map > const map_type; + typedef transform_view transformed_type; + typedef boost::fusion::result_of::begin::type i_type; + typedef boost::fusion::result_of::deref_data::type r_type; + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + // compile test only + // make sure result_of::deref_data will not return a reference to temp object + typedef map > const map_type; + typedef transform_view transformed_type; + typedef boost::fusion::result_of::begin::type i_type; + typedef boost::fusion::result_of::deref_data::type r_type; + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + // compile test only + // make sure result_of::deref_data will not const for non-constant references + typedef map > const map_type; + typedef transform_view transformed_type; + typedef boost::fusion::result_of::begin::type i_type; + typedef boost::fusion::result_of::deref_data::type r_type; + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + return boost::report_errors(); }