diff --git a/appveyor.yml b/appveyor.yml index 13dc44a7..debd336b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,15 +11,19 @@ environment: matrix: - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 TOOLSET: msvc-9.0 + ADDRMD: 32 CXXSTD: latest # fake - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 TOOLSET: msvc-10.0 + ADDRMD: 32 CXXSTD: latest # fake - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 TOOLSET: msvc-11.0 + ADDRMD: 32 CXXSTD: latest # fake - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 TOOLSET: msvc-12.0 + ADDRMD: 32 CXXSTD: latest # fake - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 TOOLSET: msvc-14.0 @@ -88,4 +92,5 @@ install: build: off test_script: - - b2 -j%NUMBER_OF_PROCESSORS% --hash libs/fusion/test toolset=%TOOLSET% cxxstd=%CXXSTD% + - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% + - b2 -j%NUMBER_OF_PROCESSORS% --hash libs/fusion/test toolset=%TOOLSET% cxxstd=%CXXSTD% %ADDRMD% 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/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/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 6f50fe21..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] @@ -360,6 +363,8 @@ 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__) +* __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 f39fb7fa..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 @@ -328,9 +329,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] @@ -364,7 +363,8 @@ its underlying sequence or sequences. * __forward_sequence__, __bidirectional_sequence__ or __random_access_sequence__ depending on the traversal characteristics (see -__traversal_concept__) of its underlying sequence. +__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]] @@ -381,9 +381,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]] @@ -667,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/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/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(); +} + 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(); }