diff --git a/doc/fusion.qbk b/doc/fusion.qbk index 6d6987d5..f7a5bf76 100644 --- a/doc/fusion.qbk +++ b/doc/fusion.qbk @@ -130,6 +130,7 @@ [def __reverse_view__ [link fusion.view.reverse_view `reverse_view`]] [def __zip_view__ [link fusion.view.zip_view `zip_view`]] [def __flatten_view__ [link fusion.view.flatten_view `flatten_view`]] +[def __identity_view__ [link fusion.view.identity_view `identity_view`]] [def __array__ [link fusion.adapted.array array]] [def __std_pair__ [link fusion.adapted.std__pair `std::pair`]] diff --git a/doc/html/index.html b/doc/html/index.html index 957609a9..9f0f14da 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -163,6 +163,7 @@
zip_view
transform_view
reverse_view
+
identity_view
nview
repetitive_view
flatten_view
diff --git a/doc/organization.qbk b/doc/organization.qbk index b7166f5d..b062e6ed 100644 --- a/doc/organization.qbk +++ b/doc/organization.qbk @@ -60,6 +60,7 @@ link against. * single_view * transform_view * zip_view + * identity_view * container * deque * list diff --git a/doc/sequence.qbk b/doc/sequence.qbk index b193b8e9..554d951f 100644 --- a/doc/sequence.qbk +++ b/doc/sequence.qbk @@ -133,6 +133,7 @@ For any Forward Sequence s the following invariants always hold: * __transform_view__ * __reverse_view__ * __zip_view__ +* __identity_view__ [endsect] @@ -201,6 +202,7 @@ are not defined in __forward_sequence__. * __iterator_range__ (where adapted sequence is a Bidirectional Sequence) * __transform_view__ (where adapted sequence is a Bidirectional Sequence) * __zip_view__ (where adapted sequences are models of Bidirectional Sequence) +* __identity_view__ (where adapted sequence is a Bidirectional Sequence) [endsect] @@ -289,6 +291,7 @@ are not defined in __bidirectional_sequence__. * __iterator_range__ (where adapted sequence is a Random Access Sequence) * __transform_view__ (where adapted sequence is a Random Access Sequence) * __zip_view__ (where adapted sequences are models of Random Access Sequence) +* __identity_view__ (where adapted sequence is a Random Access Sequence) [endsect] @@ -361,6 +364,7 @@ you can use `__result_of_value_at_key__`.] * __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__) +* __identity_view__ (where adapted sequence is an __associative_sequence__ and a __forward_sequence__) [endsect] diff --git a/doc/view.qbk b/doc/view.qbk index d99b325f..a3ad4d09 100644 --- a/doc/view.qbk +++ b/doc/view.qbk @@ -1,6 +1,7 @@ [/============================================================================== Copyright (C) 2001-2011 Joel de Guzman Copyright (C) 2006 Dan Marsden + Copyright (c) 2022 Denis Mikhailov Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -664,4 +665,60 @@ defined in __forward_sequence__. [endsect] +[section identity_view] + +[heading Description] + +`identity_view` presents underlying sequence unchanged. + +[heading Header] + + #include + #include + +[heading Synopsis] + + template + struct identity_view; + +[heading Template parameters] + +[table + [[Parameter] [Description] [Default]] + [[`Sequence`] [A __forward_sequence__] []] +] + +[heading Model of] + +* 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 + [[`IV`] [An `identity_view` type]] + [[`s`] [An instance of `Sequence`]] + [[`iv`, `iv2`] [Instances of `identity_view`]] +] + +[heading Expression Semantics] + +Semantics of an expression is defined only where it differs from, or is not +defined in the implemented models. + +[table + [[Expression] [Semantics]] + [[`IV(s)`] [Creates an `identity_view` given sequence, `s`.]] + [[`IV(iv)`] [Copy constructs an `identity_view` from another `identity_view`, `iv`.]] + [[`iv = iv2`] [Assigns to an `identity_view`, `iv`, from another `identity_view`, `iv2`.]] +] + +[heading Example] + typedef __vector__ vector_type; + vector_type vec(2, 5, 3.3); + + __identity_view__ identity(vec); + std::cout << identity << std::endl; // (2 5 3.3) + +[endsect] + [endsect] diff --git a/include/boost/fusion/include/identity_view.hpp b/include/boost/fusion/include/identity_view.hpp new file mode 100644 index 00000000..bb27d27b --- /dev/null +++ b/include/boost/fusion/include/identity_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + 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(FUSION_INCLUDE_IDENTITY_VIEW) +#define FUSION_INCLUDE_IDENTITY_VIEW + +#include +#include + +#endif \ No newline at end of file diff --git a/include/boost/fusion/view.hpp b/include/boost/fusion/view.hpp index 4cb49122..0d8ded42 100644 --- a/include/boost/fusion/view.hpp +++ b/include/boost/fusion/view.hpp @@ -17,5 +17,6 @@ #include #include #include +#include #endif diff --git a/include/boost/fusion/view/identity_view.hpp b/include/boost/fusion/view/identity_view.hpp new file mode 100644 index 00000000..72414cbe --- /dev/null +++ b/include/boost/fusion/view/identity_view.hpp @@ -0,0 +1,14 @@ +/*============================================================================= + 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_SEQUENCE_IDENTITY_VIEW_HPP_INCLUDED) +#define BOOST_FUSION_SEQUENCE_IDENTITY_VIEW_HPP_INCLUDED + +#include +#include + + +#endif \ No newline at end of file diff --git a/include/boost/fusion/view/identity_view/identity_view.hpp b/include/boost/fusion/view/identity_view/identity_view.hpp new file mode 100644 index 00000000..e7efdb7a --- /dev/null +++ b/include/boost/fusion/view/identity_view/identity_view.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + 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_IDENTITY_VIEW_HPP_INCLUDED) +#define BOOST_FUSION_IDENTITY_VIEW_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost { namespace fusion { + namespace detail { + struct identity : boost::identity + { + }; + } +}} + +namespace boost { + template + struct result_of + { + typedef T type; + }; +} + +namespace boost { namespace fusion { + template struct identity_view + : transform_view + { + typedef transform_view base_type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + identity_view(Sequence& in_seq) + : base_type(in_seq, detail::identity()) {} + }; +}} + +#endif diff --git a/test/Jamfile b/test/Jamfile index e55b15ad..13dd35c5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -156,6 +156,7 @@ project : BOOST_FUSION_DISABLE_VARIADIC_VECTOR : tuple_traits__no_variadic ] [ run sequence/transform_view.cpp ] + [ run sequence/identity_view.cpp ] [ run sequence/vector_comparison.cpp ] [ run sequence/vector_construction.cpp ] [ run sequence/vector_conversion.cpp ] diff --git a/test/sequence/identity_view.cpp b/test/sequence/identity_view.cpp new file mode 100644 index 00000000..e74f9294 --- /dev/null +++ b/test/sequence/identity_view.cpp @@ -0,0 +1,193 @@ +/*============================================================================= + 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 +#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 +#include +#include +#include + +struct abstract +{ + virtual void foo() = 0; +}; + +int +main() +{ + using namespace boost::fusion; + + std::cout << tuple_open('['); + std::cout << tuple_close(']'); + std::cout << tuple_delimiter(", "); + +/// Testing the identity_view + + { + typedef boost::mpl::range_c sequence_type; + sequence_type sequence; + typedef identity_view xform_type; + xform_type xform(sequence); + + std::cout << xform << std::endl; + BOOST_TEST((xform == make_vector(5, 6, 7, 8))); + + typedef boost::fusion::result_of::begin::type first_type; + first_type first_it(boost::fusion::begin(xform)); + + typedef boost::fusion::result_of::next::type next_type; + next_type next_it(boost::fusion::next(first_it)); + BOOST_TEST((*next_it == 6)); + BOOST_TEST((*boost::fusion::prior(next_it) == 5)); + BOOST_TEST((boost::fusion::distance(first_it, next_it) == 1)); + + BOOST_TEST((*boost::fusion::advance_c<3>(boost::fusion::begin(xform)) == 8)); + BOOST_TEST((boost::fusion::at_c<2>(xform) == 7)); + BOOST_MPL_ASSERT((boost::is_same::type, boost::mpl::integral_c >)); + } + + { + typedef vector sequence_type; + sequence_type seq; + identity_view ident(seq); + copy(make_vector(1, 2, 3, 4, 5), ident); + std::cout << seq << std::endl; + BOOST_TEST((seq == make_vector(1, 2, 3, 4, 5))); + } + + /// Associative + { + typedef map< + pair + , pair + , pair > + map_type; + typedef identity_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); + + 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 identity_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 identity_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 identity_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(); +} +