diff --git a/.travis.yml b/.travis.yml index 2d8ab7cc8..7b6bcfc35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -123,7 +123,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-3.5 CXXSTD=03,11,14,1z + env: TOOLSET=clang-3.5 CXXSTD=03,11,14,1z CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -131,7 +131,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-3.6 CXXSTD=03,11,14,1z + env: TOOLSET=clang-3.6 CXXSTD=03,11,14,1z CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -139,7 +139,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-3.7 CXXSTD=03,11,14,1z + env: TOOLSET=clang-3.7 CXXSTD=03,11,14,1z CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -147,7 +147,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-3.8 CXXSTD=03,11,14,1z + env: TOOLSET=clang-3.8 CXXSTD=03,11,14,1z CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -155,7 +155,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-3.9 CXXSTD=03,11,14,1z + env: TOOLSET=clang-3.9 CXXSTD=03,11,14,1z CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -163,7 +163,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-4.0 CXXSTD=03,11,14,1z + env: TOOLSET=clang-4.0 CXXSTD=03,11,14,1z CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -171,7 +171,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-5.0 CXXSTD=03,11,14,17,2a + env: TOOLSET=clang-5.0 CXXSTD=03,11,14,17,2a CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -181,7 +181,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-6.0 CXXSTD=03,11,14,17,2a + env: TOOLSET=clang-6.0 CXXSTD=03,11,14,17,2a CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -191,7 +191,7 @@ matrix: - os: linux dist: xenial - env: TOOLSET=clang-7.0 CXXSTD=03,11,14,17,2a + env: TOOLSET=clang-7.0 CXXSTD=03,11,14,17,2a CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" addons: apt: packages: @@ -200,7 +200,7 @@ matrix: - llvm-toolchain-xenial-7 - os: osx - env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z + env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z CXXFLAGS="-DBOOST_PFR_USE_CPP17=0" install: - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true @@ -236,6 +236,7 @@ install: - git submodule init libs/type_traits - git submodule init libs/typeof - git submodule init libs/utility + - git submodule init libs/pfr - git submodule init libs/headers tools/boost_install tools/build - git submodule update diff --git a/CMakeLists.txt b/CMakeLists.txt index 2972717b1..4c838a05b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,4 +26,5 @@ target_link_libraries(boost_fusion Boost::type_traits Boost::typeof Boost::utility + Boost::pfr ) diff --git a/appveyor.yml b/appveyor.yml index 13dc44a75..5e33087c9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -78,6 +78,7 @@ install: - git submodule init libs/type_traits - git submodule init libs/typeof - git submodule init libs/utility + - git submodule init libs/pfr - git submodule init libs/headers tools/boost_install tools/build - git submodule update diff --git a/include/boost/fusion/adapted.hpp b/include/boost/fusion/adapted.hpp index 5bc33899c..43cdeff2b 100644 --- a/include/boost/fusion/adapted.hpp +++ b/include/boost/fusion/adapted.hpp @@ -23,4 +23,12 @@ #include #endif +// Unfortunately, there is no way to determine the compatibility of the pfr library with the current compiler. +// The "boost/fusion/adapted/pfr.hpp" include has been commented out to ensure backward compatibility +// Please include it manually in your project + +// #if !defined(BOOST_FUSION_NO_PFR) +// #include +// #endif + #endif diff --git a/include/boost/fusion/adapted/pfr.hpp b/include/boost/fusion/adapted/pfr.hpp new file mode 100644 index 000000000..2094a1091 --- /dev/null +++ b/include/boost/fusion/adapted/pfr.hpp @@ -0,0 +1,23 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_HPP +#define BOOST_FUSION_ADAPTED_PFR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif //BOOST_FUSION_ADAPTED_PFR_HPP diff --git a/include/boost/fusion/adapted/pfr/adapt_pfr.hpp b/include/boost/fusion/adapted/pfr/adapt_pfr.hpp new file mode 100644 index 000000000..bc889fdda --- /dev/null +++ b/include/boost/fusion/adapted/pfr/adapt_pfr.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_STRUCT_ADAPT_PFR_HPP +#define BOOST_FUSION_ADAPTED_STRUCT_ADAPT_PFR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOST_FUSION_ADAPT_TPL_PFR(TEMPLATE_PARAMS_SEQ,NAME_SEQ) \ + BOOST_FUSION_ADAPT_PFR_BASE( \ + (1)TEMPLATE_PARAMS_SEQ, \ + (1)NAME_SEQ, \ + pfr_tag) + +#define BOOST_FUSION_ADAPT_PFR(NAME) \ + BOOST_FUSION_ADAPT_PFR_BASE( \ + (0), \ + (0)(NAME), \ + pfr_tag) + +#endif //BOOST_FUSION_ADAPTED_STRUCT_ADAPT_PFR_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/adapt_base.hpp b/include/boost/fusion/adapted/pfr/detail/adapt_base.hpp new file mode 100644 index 000000000..b107c671b --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/adapt_base.hpp @@ -0,0 +1,134 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_ADAPT_BASE_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_ADAPT_BASE_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BOOST_FUSION_ADAPT_PFR_UNPACK_NAME_TEMPLATE_PARAMS(SEQ) \ + BOOST_PP_SEQ_HEAD(SEQ) \ + BOOST_PP_EMPTY() + +#define BOOST_FUSION_ADAPT_PFR_UNPACK_NAME(SEQ) \ + BOOST_PP_IF( \ + BOOST_PP_SEQ_HEAD(SEQ), \ + BOOST_FUSION_ADAPT_PFR_UNPACK_NAME_TEMPLATE_PARAMS, \ + BOOST_PP_SEQ_HEAD)(BOOST_PP_SEQ_TAIL(SEQ)) + +#define BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS_IMPL_C(R, _, ELEM) \ + (typename ELEM) +#define BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS_IMPL(SEQ) \ + BOOST_PP_SEQ_ENUM( \ + BOOST_PP_SEQ_FOR_EACH( \ + BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS_IMPL_C, \ + _, \ + BOOST_PP_SEQ_TAIL(SEQ))) +#define BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS(SEQ) \ + BOOST_PP_IF( \ + BOOST_PP_SEQ_HEAD(SEQ), \ + BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS_IMPL, \ + BOOST_PP_TUPLE_EAT(1))(SEQ) + +#ifdef BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS +# define BOOST_FUSION_ADAPT_PFR_TAG_OF_SPECIALIZATION( \ + MODIFIER, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ + \ + template< \ + BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ + > \ + struct tag_of< \ + BOOST_FUSION_ADAPT_PFR_UNPACK_NAME(NAME_SEQ) MODIFIER \ + , void \ + > \ + { \ + typedef TAG type; \ + }; +#else +# define BOOST_FUSION_ADAPT_PFR_TAG_OF_SPECIALIZATION( \ + MODIFIER, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ + \ + template< \ + BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ + > \ + struct tag_of \ + { \ + typedef TAG type; \ + }; +#endif + +#define BOOST_FUSION_ADAPT_PFR_BASE( \ + TEMPLATE_PARAMS_SEQ, \ + NAME_SEQ, \ + TAG) \ + \ +namespace boost \ +{ \ + namespace fusion \ + { \ + namespace traits \ + { \ + BOOST_FUSION_ADAPT_PFR_TAG_OF_SPECIALIZATION( \ + BOOST_PP_EMPTY(), TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ + BOOST_FUSION_ADAPT_PFR_TAG_OF_SPECIALIZATION( \ + const, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ + } \ + } \ + \ + namespace mpl \ + { \ + template \ + struct sequence_tag; \ + \ + template< \ + BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS( \ + TEMPLATE_PARAMS_SEQ) \ + > \ + struct sequence_tag \ + { \ + typedef fusion::fusion_sequence_tag type; \ + }; \ + \ + template< \ + BOOST_FUSION_ADAPT_PFR_UNPACK_TEMPLATE_PARAMS( \ + TEMPLATE_PARAMS_SEQ) \ + > \ + struct sequence_tag< \ + BOOST_FUSION_ADAPT_PFR_UNPACK_NAME(NAME_SEQ) const \ + > \ + { \ + typedef fusion::fusion_sequence_tag type; \ + }; \ + } \ +} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_ADAPT_BASE_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/at_impl.hpp b/include/boost/fusion/adapted/pfr/detail/at_impl.hpp new file mode 100644 index 000000000..87331687b --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/at_impl.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_AT_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_AT_IMPL_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct at_impl; + + template<> + struct at_impl + { + template + struct apply + { + typedef typename remove_const::type seq_type; + typedef typename boost::pfr::tuple_element::type element; + + typedef typename + mpl::if_< + is_const + , typename fusion::detail::cref_result::type + , typename fusion::detail::ref_result::type + >::type + type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + static type + call(Sequence& seq) + { + return boost::pfr::get(seq); + } + }; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_AT_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/begin_impl.hpp b/include/boost/fusion/adapted/pfr/detail/begin_impl.hpp new file mode 100644 index 000000000..c7af09111 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/begin_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_BEGIN_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_BEGIN_IMPL_HPP + +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef pfr_iterator type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_BEGIN_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/category_of_impl.hpp b/include/boost/fusion/adapted/pfr/detail/category_of_impl.hpp new file mode 100644 index 000000000..e968ddd91 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/category_of_impl.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_CATEGORY_OF_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_CATEGORY_OF_IMPL_HPP + +namespace boost { namespace fusion +{ + struct pfr_tag; + struct random_access_traversal_tag; + + namespace extension + { + template + struct category_of_impl; + + template<> + struct category_of_impl + { + template + struct apply + { + typedef random_access_traversal_tag type; + }; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_CATEGORY_OF_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/end_impl.hpp b/include/boost/fusion/adapted/pfr/detail/end_impl.hpp new file mode 100644 index 000000000..4ab5d6a4f --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/end_impl.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_END_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_END_IMPL_HPP + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct end_impl; + + template<> + struct end_impl + { + template + struct apply + { + typedef typename remove_const::type seq_type; + static int const size = boost::pfr::tuple_size::value; + typedef pfr_iterator type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_END_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/is_sequence_impl.hpp b/include/boost/fusion/adapted/pfr/detail/is_sequence_impl.hpp new file mode 100644 index 000000000..ca95ac77e --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/is_sequence_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_IS_SEQUENCE_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_IS_SEQUENCE_IMPL_HPP + +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct is_sequence_impl; + + template<> + struct is_sequence_impl + { + template + struct apply : mpl::true_ {}; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_IS_SEQUENCE_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/is_view_impl.hpp b/include/boost/fusion/adapted/pfr/detail/is_view_impl.hpp new file mode 100644 index 000000000..2f68c8ce4 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/is_view_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_IS_VIEW_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_IS_VIEW_IMPL_HPP + +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct is_view_impl; + + template<> + struct is_view_impl + { + template + struct apply : mpl::false_ {}; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_IS_VIEW_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/size_impl.hpp b/include/boost/fusion/adapted/pfr/detail/size_impl.hpp new file mode 100644 index 000000000..f0f960184 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/size_impl.hpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_VIEW_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_VIEW_IMPL_HPP + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct size_impl; + + template<> + struct size_impl + { + template + struct apply : + mpl::int_::type>::value + > + {}; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_VIEW_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/detail/value_at_impl.hpp b/include/boost/fusion/adapted/pfr/detail/value_at_impl.hpp new file mode 100644 index 000000000..06b06225d --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/value_at_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_DETAIL_VALUE_AT_IMPL_HPP +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_VALUE_AT_IMPL_HPP + +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct value_at_impl; + + template<> + struct value_at_impl + { + template + struct apply : boost::pfr::tuple_element {}; + }; + } +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_DETAIL_VALUE_AT_IMPL_HPP diff --git a/include/boost/fusion/adapted/pfr/pfr_iterator.hpp b/include/boost/fusion/adapted/pfr/pfr_iterator.hpp new file mode 100644 index 000000000..488aa694b --- /dev/null +++ b/include/boost/fusion/adapted/pfr/pfr_iterator.hpp @@ -0,0 +1,111 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_ITERATOR_HPP +#define BOOST_FUSION_ADAPTED_PFR_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct random_access_traversal_tag; + + template + struct pfr_iterator_identity; + + template + struct pfr_iterator + : iterator_facade< + pfr_iterator + , random_access_traversal_tag> + { + typedef Tuple tuple_type; + static int const index = Index; + typedef pfr_iterator_identity< + typename add_const::type, Index> + identity; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + explicit pfr_iterator(Tuple& tuple) + : tuple(tuple) {} + + Tuple& tuple; + + template + struct value_of + : boost::pfr::tuple_element::type> {}; + + template + struct deref + { + typedef typename value_of::type element; + typedef typename + mpl::if_< + is_const + , typename fusion::detail::cref_result::type + , typename fusion::detail::ref_result::type + >::type + type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + static type + call(Iterator const& iter) + { + return boost::pfr::get(iter.tuple); + } + }; + + template + struct advance + { + static int const index = Iterator::index; + typedef typename Iterator::tuple_type tuple_type; + typedef pfr_iterator type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + static type + call(Iterator const& i) + { + return type(i.tuple); + } + }; + + template + struct next : advance> {}; + + template + struct prior : advance> {}; + + template + struct equal_to + : is_same {}; + + template + struct distance + { + typedef mpl::int_ type; + + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + static type + call(First const&, Last const&) + { + return type(); + } + }; + }; +}} + +#endif //BOOST_FUSION_ADAPTED_PFR_ITERATOR_HPP diff --git a/include/boost/fusion/include/adapt_pfr.hpp b/include/boost/fusion/include/adapt_pfr.hpp new file mode 100644 index 000000000..7344b60b0 --- /dev/null +++ b/include/boost/fusion/include/adapt_pfr.hpp @@ -0,0 +1,14 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_INCLUDE_ADAPT_PFR_HPP +#define BOOST_FUSION_INCLUDE_ADAPT_PFR_HPP + +#include +#include + +#endif diff --git a/include/boost/fusion/include/pfr.hpp b/include/boost/fusion/include/pfr.hpp new file mode 100644 index 000000000..778a957f5 --- /dev/null +++ b/include/boost/fusion/include/pfr.hpp @@ -0,0 +1,14 @@ +/*============================================================================= + Copyright (c) 2021 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_INCLUDE_PFR_HPP +#define BOOST_FUSION_INCLUDE_PFR_HPP + +#include +#include + +#endif diff --git a/test/Jamfile b/test/Jamfile index e55b15ad2..2e2a96bfd 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -68,6 +68,8 @@ project [ run algorithm/flatten.cpp ] [ compile algorithm/ticket-5490.cpp ] + [ compile include/adapted.cpp ] + [ run sequence/as_deque.cpp ] [ run sequence/as_list.cpp ] [ run sequence/as_map.cpp ] @@ -240,6 +242,15 @@ project [ compile sequence/github-159.cpp ] [ run sequence/github-176.cpp ] + [ run sequence/pfr.cpp : : + : BOOST_PFR_USE_LOOPHOLE=0 [ requires cxx14_constexpr ] ] + [ run sequence/pfr_empty.cpp : : + : BOOST_PFR_USE_LOOPHOLE=0 [ requires cxx14_constexpr ] ] + [ run sequence/tpl_pfr.cpp : : + : BOOST_PFR_USE_LOOPHOLE=0 [ requires cxx14_constexpr ] ] + [ run sequence/tpl_pfr_empty.cpp : : + : BOOST_PFR_USE_LOOPHOLE=0 [ requires cxx14_constexpr ] ] + [ compile sequence/size.cpp ] [ run functional/fused.cpp ] diff --git a/test/include/adapted.cpp b/test/include/adapted.cpp new file mode 100644 index 000000000..35c95cb08 --- /dev/null +++ b/test/include/adapted.cpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2021 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 + +/// to make sure that the pfr adapter does not generate new compilation errors in old code that depends on inclusion +/// adapted.hpp + +int +main() +{ + return boost::report_errors(); +} diff --git a/test/sequence/pfr.cpp b/test/sequence/pfr.cpp new file mode 100644 index 000000000..63401ff42 --- /dev/null +++ b/test/sequence/pfr.cpp @@ -0,0 +1,155 @@ +/*============================================================================= + Copyright (c) 2021 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 + +namespace namespaced_type { + typedef int integer; +} + +namespace ns { + struct point { + int x; + int y; + namespaced_type::integer z; + }; + + // Testing non-constexpr compatible types +#if BOOST_PFR_USE_CPP17 != 0 + struct employee { + std::string name; + std::string nickname; + }; +#endif // BOOST_PFR_USE_CPP17 +} + +BOOST_FUSION_ADAPT_PFR(ns::point); +#if BOOST_PFR_USE_CPP17 != 0 +BOOST_FUSION_ADAPT_PFR(ns::employee); +#endif // BOOST_PFR_USE_CPP17 + +struct s { int m; }; +BOOST_FUSION_ADAPT_PFR(s); + +struct empty_struct {}; +BOOST_FUSION_ADAPT_PFR(empty_struct); + +int +main() +{ + using namespace boost::fusion; + using namespace boost; + using ns::point; + + std::cout << tuple_open('['); + std::cout << tuple_close(']'); + std::cout << tuple_delimiter(", "); + + { + BOOST_MPL_ASSERT_NOT((traits::is_view)); + BOOST_STATIC_ASSERT(!traits::is_view::value); + point p = {123, 456, 789}; + + std::cout << at_c<0>(p) << std::endl; + std::cout << at_c<1>(p) << std::endl; + std::cout << at_c<2>(p) << std::endl; + std::cout << p << std::endl; + BOOST_TEST(p == make_vector(123, 456, 789)); + + at_c<0>(p) = 6; + at_c<1>(p) = 9; + at_c<2>(p) = 12; + BOOST_TEST(p == make_vector(6, 9, 12)); + + BOOST_STATIC_ASSERT(boost::fusion::result_of::size::value == 3); + BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty::value); + + BOOST_TEST(front(p) == 6); + BOOST_TEST(back(p) == 12); + } + + { + vector v1(4, 2.f, 2); + point v2 = {5, 3, 3}; + vector v3(5, 4., 4); + BOOST_TEST(v1 < v2); + BOOST_TEST(v1 <= v2); + BOOST_TEST(v2 > v1); + BOOST_TEST(v2 >= v1); + BOOST_TEST(v2 < v3); + BOOST_TEST(v2 <= v3); + BOOST_TEST(v3 > v2); + BOOST_TEST(v3 >= v2); + } + + { + // conversion from point to vector + point p = {5, 3, 3}; + vector v(p); + v = p; + } + + { + // conversion from point to list + point p = {5, 3, 3}; + list l(p); + l = p; + } + + { // begin/end + using namespace boost::fusion; + using boost::is_same; + + typedef boost::fusion::result_of::begin::type b; + typedef boost::fusion::result_of::end::type e; + // this fails + BOOST_MPL_ASSERT((is_same::type, e>)); + } + + { + BOOST_MPL_ASSERT((mpl::is_sequence)); + BOOST_MPL_ASSERT((boost::is_same< + boost::fusion::result_of::value_at_c::type + , mpl::front::type>)); + } + +#if BOOST_PFR_USE_CPP17 != 0 + { + ns::employee emp{"John Doe", "jdoe"}; + std::cout << at_c<0>(emp) << std::endl; + std::cout << at_c<1>(emp) << std::endl; + + fusion::vector v1("John Doe", "jdoe"); + BOOST_TEST(emp == v1); + } +#endif // BOOST_PFR_USE_CPP17 + + return boost::report_errors(); +} diff --git a/test/sequence/pfr_empty.cpp b/test/sequence/pfr_empty.cpp new file mode 100644 index 000000000..00548b644 --- /dev/null +++ b/test/sequence/pfr_empty.cpp @@ -0,0 +1,95 @@ +/*============================================================================= + Copyright (c) 2021 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 + +struct empty_struct {}; +BOOST_FUSION_ADAPT_PFR(empty_struct); + +int +main() +{ + using namespace boost::fusion; + using namespace boost; + + std::cout << tuple_open('['); + std::cout << tuple_close(']'); + std::cout << tuple_delimiter(", "); + + { + BOOST_MPL_ASSERT_NOT((traits::is_view)); + BOOST_STATIC_ASSERT(!traits::is_view::value); + empty_struct e; + + std::cout << e << std::endl; + BOOST_TEST(e == make_vector()); + + BOOST_STATIC_ASSERT(fusion::result_of::size::value == 0); + BOOST_MPL_ASSERT((fusion::result_of::empty)); + + BOOST_MPL_ASSERT((fusion::result_of::equal_to< + fusion::result_of::begin::type, + fusion::result_of::end::type>)); + } + + { + int counter = 0; + empty_struct empty; + boost::fusion::for_each(empty, [&](){counter+=1;}); + BOOST_TEST(counter == 0); + } + + { + fusion::vector<> v; + empty_struct e; + BOOST_TEST(v == e); + BOOST_TEST_NOT(e != v); + BOOST_TEST_NOT(v < e); + BOOST_TEST(v <= e); + BOOST_TEST_NOT(e > v); + BOOST_TEST(e >= v); + } + + { + empty_struct e; + + // conversion from empty_struct to vector + fusion::vector<> v(e); + v = e; + + // FIXME + // conversion from empty_struct to list + //fusion::list<> l(e); + //l = e; + } + + BOOST_MPL_ASSERT((mpl::is_sequence)); + + return boost::report_errors(); +} \ No newline at end of file diff --git a/test/sequence/tpl_pfr.cpp b/test/sequence/tpl_pfr.cpp new file mode 100644 index 000000000..e7445cd02 --- /dev/null +++ b/test/sequence/tpl_pfr.cpp @@ -0,0 +1,121 @@ +/*============================================================================= + Copyright (c) 2021 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 + +namespace ns +{ + template + struct point + { + X x; + Y y; + int z; + }; +} + +BOOST_FUSION_ADAPT_TPL_PFR((X)(Y),(ns::point)(X)(Y)); + +template +struct s { M m; }; +BOOST_FUSION_ADAPT_TPL_PFR((M), (s)(M)); + +int +main() +{ + using namespace boost::fusion; + + typedef ns::point point; + + std::cout << tuple_open('['); + std::cout << tuple_close(']'); + std::cout << tuple_delimiter(", "); + + { + BOOST_MPL_ASSERT_NOT((traits::is_view)); + BOOST_STATIC_ASSERT(!traits::is_view::value); + point p = {123, 456, 789}; + + std::cout << at_c<0>(p) << std::endl; + std::cout << at_c<1>(p) << std::endl; + std::cout << at_c<2>(p) << std::endl; + std::cout << p << std::endl; + BOOST_TEST(p == make_vector(123, 456, 789)); + + at_c<0>(p) = 6; + at_c<1>(p) = 9; + at_c<2>(p) = 12; + BOOST_TEST(p == make_vector(6, 9, 12)); + + BOOST_STATIC_ASSERT(boost::fusion::result_of::size::value == 3); + BOOST_STATIC_ASSERT(!boost::fusion::result_of::empty::value); + + BOOST_TEST(front(p) == 6); + BOOST_TEST(back(p) == 12); + } + + { + vector v1(4, 2.f, 2); + point v2 = {5, 3, 3}; + vector v3(5, 4., 4); + BOOST_TEST(v1 < v2); + BOOST_TEST(v1 <= v2); + BOOST_TEST(v2 > v1); + BOOST_TEST(v2 >= v1); + BOOST_TEST(v2 < v3); + BOOST_TEST(v2 <= v3); + BOOST_TEST(v3 > v2); + BOOST_TEST(v3 >= v2); + } + + { + // conversion from point to vector + point p = {5, 3, 3}; + vector v(p); + v = p; + } + + { + // conversion from point to list + point p = {5, 3, 3}; + list l(p); + l = p; + } + + { // begin/end + using namespace boost::fusion; + + typedef boost::fusion::result_of::begin >::type b; + typedef boost::fusion::result_of::end >::type e; + // this fails + BOOST_MPL_ASSERT((boost::is_same::type, e>)); + } + + return boost::report_errors(); +} \ No newline at end of file diff --git a/test/sequence/tpl_pfr_empty.cpp b/test/sequence/tpl_pfr_empty.cpp new file mode 100644 index 000000000..01a5094b6 --- /dev/null +++ b/test/sequence/tpl_pfr_empty.cpp @@ -0,0 +1,96 @@ +/*============================================================================= + Copyright (c) 2021 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 + +template +class empty_struct{}; +BOOST_FUSION_ADAPT_TPL_PFR((T), (empty_struct)(T)); + +int +main() +{ + using namespace boost::fusion; + using namespace boost; + + std::cout << tuple_open('['); + std::cout << tuple_close(']'); + std::cout << tuple_delimiter(", "); + + { + BOOST_MPL_ASSERT_NOT((traits::is_view >)); + BOOST_STATIC_ASSERT(!traits::is_view >::value); + empty_struct e; + + std::cout << e << std::endl; + BOOST_TEST(e == make_vector()); + + BOOST_STATIC_ASSERT(fusion::result_of::size >::value == 0); + BOOST_MPL_ASSERT((fusion::result_of::empty >)); + + BOOST_MPL_ASSERT((fusion::result_of::equal_to< + fusion::result_of::begin >::type, + fusion::result_of::end >::type>)); + } + + { + int counter = 0; + empty_struct empty; + boost::fusion::for_each(empty, [&](){counter+=1;}); + BOOST_TEST(counter == 0); + } + + { + fusion::vector<> v; + empty_struct e; + BOOST_TEST(v == e); + BOOST_TEST_NOT(v != e); + BOOST_TEST_NOT(v < e); + BOOST_TEST(v <= e); + BOOST_TEST_NOT(v > e); + BOOST_TEST(v >= e); + } + + { + empty_struct e; + + // conversion from empty_struct to vector + fusion::vector<> v(e); + v = e; + + // FIXME + // conversion from empty_struct to list + //fusion::list<> l(e); + //l = e; + } + + BOOST_MPL_ASSERT((mpl::is_sequence >)); + + return boost::report_errors(); +} \ No newline at end of file