diff --git a/CMakeLists.txt b/CMakeLists.txt index 707b4f898..527d69400 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,4 +23,5 @@ target_link_libraries(boost_fusion Boost::type_traits Boost::typeof Boost::utility + Boost::pfr ) diff --git a/appveyor.yml b/appveyor.yml index debd336bb..539f1a331 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -82,6 +82,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/doc/adapted.qbk b/doc/adapted.qbk index d14086196..a5e7b9bc6 100644 --- a/doc/adapted.qbk +++ b/doc/adapted.qbk @@ -2,6 +2,7 @@ Copyright (C) 2001-2011 Joel de Guzman Copyright (C) 2006 Dan Marsden Copyright (C) 2010 Christopher Schmidt + 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 @@ -1127,6 +1128,116 @@ __adt_attribute_proxy__ [endsect] +[section:adapt_pfr BOOST_FUSION_ADAPT_PFR] + +[caution This macro requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported.] +[important Also, please read __boost_pfr_lims__ before using this macro. Pay special attention to the SimpleAggregate concept.] + +[heading Description] +BOOST_FUSION_ADAPT_PFR is a macro that can be used to generate all the +necessary boilerplate to make an arbitrary struct a model of +__random_access_sequence__. +This macro only works with structures that satisfy the concept of SimpleAggregate. + +[heading Synopsis] + BOOST_FUSION_ADAPT_PFR(aggregate_name) + +[heading Semantics] + +The above macro generates the necessary code to adapt `aggregate_name` +as a model of __random_access_sequence__. + +__boost_pfr__ takes responsibility for extracting each of the struct members that +are part of the sequence. + +The macro should be used at global scope, and `aggregate_name` should be the fully +namespace qualified name of the struct to be adapted. + +[heading Header] + + #include + #include + +[note This macro won't defined by inclusion of 'boost/fusion/adapted.hpp'. ] + +[heading Example: BOOST_FUSION_ADAPT_PFR ] + namespace demo + { + struct employee + { + std::string name; + int age; + }; + } + + // demo::employee is now a Fusion sequence + BOOST_FUSION_ADAPT_PFR(demo::employee) + +[heading See also] + +__boost_pfr__ + +[endsect] + +[section:adapt_tpl_pfr BOOST_FUSION_ADAPT_TPL_PFR] + +[caution This macro requires at least C++14! Pre C++14 compilers (C++11, C++03...) are not supported.] +[important Also, please read __boost_pfr_lims__ before using this macro. Pay special attention to the SimpleAggregate concept.] + +[heading Description] +BOOST_FUSION_ADAPT_TPL_PFR is a macro that can be used to generate all the +necessary boilerplate to make an arbitrary template struct a model of +__random_access_sequence__. +This macro only works with structures that satisfy the concept of SimpleAggregate. + +[heading Synopsis] + BOOST_FUSION_ADAPT_TPL_PFR(aggregate_name) + +[heading Semantics] + +The above macro generates the necessary code to adapt `aggregate_name` or an +arbitrary specialization of `aggregate_name` as a model of +__random_access_sequence__. + +None of the specializations of `aggregate_name` should have non-type template parameter. +The sequence `(specialization_param0)(specialization_param1)...` +declares the template parameters of the actual specialization of `struct_name` +that is adapted as a fusion sequence. +__boost_pfr__ takes responsibility for extracting each of the struct members that +are part of the sequence. + + +The macro should be used at global scope, and `aggregate_name` should be the fully +namespace qualified name of the template struct to be adapted. + +[heading Header] + + #include + #include + +[note This macro won't defined by inclusion of 'boost/fusion/adapted.hpp'. ] + +[heading Example] + namespace demo + { + template + struct employee + { + Name name; + Age age; + int employment_timestamp; + }; + } + + // Any instantiated demo::employee is now a Fusion sequence + BOOST_FUSION_ADAPT_TPL_PFR(demo::employee) + +[heading See also] + +__boost_pfr__ + +[endsect] + [section:define_struct BOOST_FUSION_DEFINE_STRUCT] BOOST_FUSION_DEFINE_STRUCT is a macro that can be used to generate all the diff --git a/doc/fusion.qbk b/doc/fusion.qbk index f7a5bf766..adb8108e3 100644 --- a/doc/fusion.qbk +++ b/doc/fusion.qbk @@ -146,6 +146,8 @@ [def __adapt_tpl_adt__ [link fusion.adapted.adapt_tpl_adt `BOOST_FUSION_ADAPT_TPL_ADT`]] [def __adapt_assoc_adt__ [link fusion.adapted.adapt_assoc_adt `BOOST_FUSION_ADAPT_ASSOC_ADT`]] [def __adapt_assoc_tpl_adt__ [link fusion.adapted.adapt_assoc_tpl_adt `BOOST_FUSION_ADAPT_ASSOC_TPL_ADT`]] +[def __adapt_pfr__ [link fusion.adapted.adapt_pfr `BOOST_FUSION_ADAPT_PFR`]] +[def __adapt_tpl_pfr__ [link fusion.adapted.adapt_tpl_pfr `BOOST_FUSION_ADAPT_TPL_PFR`]] [def __define_struct__ [link fusion.adapted.define_struct `BOOST_FUSION_DEFINE_STRUCT`]] [def __define_tpl_struct__ [link fusion.adapted.define_tpl_struct `BOOST_FUSION_DEFINE_TPL_STRUCT`]] [def __define_assoc_struct__ [link fusion.adapted.define_assoc_struct `BOOST_FUSION_DEFINE_ASSOC_STRUCT`]] diff --git a/doc/html/index.html b/doc/html/index.html index 9f0f14da5..c23fb9eed 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -186,6 +186,8 @@
BOOST_FUSION_ADAPT_TPL_ADT
BOOST_FUSION_ADAPT_ASSOC_ADT
BOOST_FUSION_ADAPT_ASSOC_TPL_ADT
+
BOOST_FUSION_ADAPT_PFR
+
BOOST_FUSION_ADAPT_TPL_PFR
BOOST_FUSION_DEFINE_STRUCT
BOOST_FUSION_DEFINE_TPL_STRUCT
BOOST_FUSION_DEFINE_STRUCT_INLINE
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..f6498e870 --- /dev/null +++ b/include/boost/fusion/adapted/pfr.hpp @@ -0,0 +1,21 @@ +/*============================================================================= + 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_ADAPTED_PFR_HPP +#define BOOST_FUSION_ADAPTED_PFR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif 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..f870f98a4 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/adapt_pfr.hpp @@ -0,0 +1,99 @@ +/*============================================================================= + 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_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_PFR(NAME) \ + \ + namespace boost { namespace fusion { \ + struct pfr_tag; \ + struct fusion_sequence_tag; \ + \ + namespace traits \ + { \ + template<> \ + struct tag_of \ + { \ + using type = pfr_tag; \ + }; \ + template<> \ + struct tag_of \ + { \ + using type = pfr_tag; \ + }; \ + } \ + }} \ + \ + namespace boost { namespace mpl \ + { \ + template \ + struct sequence_tag; \ + \ + template<> \ + struct sequence_tag \ + { \ + using type = fusion::fusion_sequence_tag; \ + }; \ + \ + template<> \ + struct sequence_tag \ + { \ + using type = fusion::fusion_sequence_tag; \ + }; \ + }} + +#define BOOST_FUSION_ADAPT_TPL_PFR(NAME) \ + \ + namespace boost { namespace fusion { \ + struct pfr_tag; \ + struct fusion_sequence_tag; \ + \ + namespace traits \ + { \ + template \ + struct tag_of> \ + { \ + using type = pfr_tag; \ + }; \ + template \ + struct tag_of const> \ + { \ + using type = pfr_tag; \ + }; \ + } \ + }} \ + \ + namespace boost { namespace mpl \ + { \ + template \ + struct sequence_tag; \ + \ + template \ + struct sequence_tag> \ + { \ + using type = fusion::fusion_sequence_tag; \ + }; \ + \ + template \ + struct sequence_tag const> \ + { \ + using type = fusion::fusion_sequence_tag; \ + }; \ + }} + +#endif 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..07278a137 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/at_impl.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_ADAPTED_PFR_DETAIL_AT_IMPL_HPP) +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_AT_IMPL_HPP + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct at_impl; + + template<> + struct at_impl + { + template + struct apply + { + using type = typename result_of::at< pfr_fields_view, N >::type; + + constexpr BOOST_FUSION_GPU_ENABLED + static type + call(Aggregate& seq) + { + return at(pfr_fields(seq)); + } + }; + }; + } +}} + +#endif 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..b75c3f9a6 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/begin_impl.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_ADAPTED_PFR_DETAIL_BEGIN_IMPL_HPP) +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_BEGIN_IMPL_HPP + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + using type = typename result_of::begin< pfr_fields_view >::type; + + constexpr BOOST_FUSION_GPU_ENABLED + static type + call(Aggregate& seq) + { + return begin(pfr_fields(seq)); + } + }; + }; + } +}} + +#endif 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..febd79c08 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/category_of_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + 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_ADAPTED_PFR_DETAIL_CATEGORY_OF_IMPL_HPP) +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_CATEGORY_OF_IMPL_HPP + +#include + +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 + { + using type = random_access_traversal_tag; + }; + }; + } +}} + +#endif 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..f2dc134ef --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/end_impl.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_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 + { + using type = typename result_of::end< pfr_fields_view >::type; + + constexpr BOOST_FUSION_GPU_ENABLED + static type + call(Aggregate& seq) + { + return end(pfr_fields(seq)); + } + }; + }; + } +}} + +#endif 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..bcbc06ef4 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/is_sequence_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + 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_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 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..77d622a37 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/is_view_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + 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_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 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..1c0737cfe --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/size_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + 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_ADAPTED_PFR_DETAIL_VIEW_IMPL_HPP) +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_VIEW_IMPL_HPP + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct size_impl; + + template<> + struct size_impl + { + template + struct apply : result_of::size< pfr_fields_view > + { + }; + }; + } +}} + +#endif 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..65b11c0f0 --- /dev/null +++ b/include/boost/fusion/adapted/pfr/detail/value_at_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + 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_ADAPTED_PFR_DETAIL_VALUE_AT_IMPL_HPP) +#define BOOST_FUSION_ADAPTED_PFR_DETAIL_VALUE_AT_IMPL_HPP + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct pfr_tag; + + namespace extension + { + template + struct value_at_impl; + + template<> + struct value_at_impl + { + template + struct apply : result_of::value_at< pfr_fields_view, N > + { + }; + }; + } +}} + +#endif diff --git a/include/boost/fusion/include/adapt_pfr.hpp b/include/boost/fusion/include/adapt_pfr.hpp new file mode 100644 index 000000000..813703f5b --- /dev/null +++ b/include/boost/fusion/include/adapt_pfr.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + 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) +==============================================================================*/ + +#ifndef BOOST_FUSION_INCLUDE_ADAPT_PFR_HPP +#define BOOST_FUSION_INCLUDE_ADAPT_PFR_HPP + +#include +#include + +#endif diff --git a/test/Jamfile b/test/Jamfile index 13dd35c55..2474dd1f1 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -68,6 +68,9 @@ project [ run algorithm/flatten.cpp ] [ compile algorithm/ticket-5490.cpp ] + [ compile include/_adapt_pfr.cpp + : [ requires cxx14_constexpr ] ] + [ run sequence/as_deque.cpp ] [ run sequence/as_list.cpp ] [ run sequence/as_map.cpp ] @@ -207,6 +210,14 @@ project [ run sequence/adapt_tpl_adt_empty.cpp ] [ run sequence/adapt_tpl_struct.cpp ] [ run sequence/adapt_tpl_struct_empty.cpp ] + [ run sequence/adapt_pfr.cpp : : + : [ requires cxx14_constexpr ] ] + [ run sequence/adapt_pfr_empty.cpp : : + : [ requires cxx14_constexpr ] ] + [ run sequence/adapt_tpl_pfr.cpp : : + : [ requires cxx14_constexpr ] ] + [ run sequence/adapt_tpl_pfr_empty.cpp : : + : [ requires cxx14_constexpr ] ] [ run sequence/adt_attribute_proxy.cpp ] [ run sequence/define_struct.cpp ] [ run sequence/define_struct_empty.cpp ] diff --git a/test/include/_adapt_pfr.cpp b/test/include/_adapt_pfr.cpp new file mode 100644 index 000000000..75cee9918 --- /dev/null +++ b/test/include/_adapt_pfr.cpp @@ -0,0 +1,13 @@ +/*============================================================================= + 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 + +int +main() +{ + return boost::report_errors(); +} \ No newline at end of file diff --git a/test/sequence/adapt_pfr.cpp b/test/sequence/adapt_pfr.cpp new file mode 100644 index 000000000..231c44958 --- /dev/null +++ b/test/sequence/adapt_pfr.cpp @@ -0,0 +1,154 @@ +/*============================================================================= + Copyright (c) 2021-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 + +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(); +} \ No newline at end of file diff --git a/test/sequence/adapt_pfr_empty.cpp b/test/sequence/adapt_pfr_empty.cpp new file mode 100644 index 000000000..0aad8b548 --- /dev/null +++ b/test/sequence/adapt_pfr_empty.cpp @@ -0,0 +1,94 @@ +/*============================================================================= + Copyright (c) 2021-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 + +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/adapt_tpl_pfr.cpp b/test/sequence/adapt_tpl_pfr.cpp new file mode 100644 index 000000000..49c168494 --- /dev/null +++ b/test/sequence/adapt_tpl_pfr.cpp @@ -0,0 +1,120 @@ +/*============================================================================= + Copyright (c) 2021-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 + +namespace ns +{ + template + struct point + { + X x; + Y y; + int z; + }; +} + +BOOST_FUSION_ADAPT_TPL_PFR(ns::point); + +template +struct s { M m; }; +BOOST_FUSION_ADAPT_TPL_PFR(s); + +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(); +} diff --git a/test/sequence/adapt_tpl_pfr_empty.cpp b/test/sequence/adapt_tpl_pfr_empty.cpp new file mode 100644 index 000000000..9549fbfcc --- /dev/null +++ b/test/sequence/adapt_tpl_pfr_empty.cpp @@ -0,0 +1,95 @@ +/*============================================================================= + Copyright (c) 2021-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 + +template +class empty_struct{}; +BOOST_FUSION_ADAPT_TPL_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(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