From 93a1fc3b87b7ad98d658b4d3e6ac564f6c64b12b Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Tue, 2 Jul 2013 13:28:20 +0100 Subject: [PATCH 01/32] Initial version of std::array for Boost.Fusion Functional, though ADL issues have not been solved (see README). --- .gitignore | 17 +++ Jamroot | 27 +++++ README.md | 13 +++ .../adapted/std_array/detail/array_size.hpp | 25 ++++ .../adapted/std_array/detail/at_impl.hpp | 45 ++++++++ .../adapted/std_array/detail/begin_impl.hpp | 41 +++++++ .../std_array/detail/category_of_impl.hpp | 35 ++++++ .../adapted/std_array/detail/end_impl.hpp | 45 ++++++++ .../std_array/detail/is_sequence_impl.hpp | 32 ++++++ .../adapted/std_array/detail/is_view_impl.hpp | 33 ++++++ .../adapted/std_array/detail/size_impl.hpp | 41 +++++++ .../std_array/detail/value_at_impl.hpp | 32 ++++++ .../adapted/std_array/std_array_iterator.hpp | 108 ++++++++++++++++++ boost/fusion/adapted/std_array/tag_of.hpp | 58 ++++++++++ libs/fusion/test/Jamfile | 22 ++++ libs/fusion/test/sequence/CMakeLists.txt | 23 ++++ libs/fusion/test/sequence/std_array.cpp | 42 +++++++ 17 files changed, 639 insertions(+) create mode 100644 .gitignore create mode 100644 Jamroot create mode 100644 README.md create mode 100644 boost/fusion/adapted/std_array/detail/array_size.hpp create mode 100644 boost/fusion/adapted/std_array/detail/at_impl.hpp create mode 100644 boost/fusion/adapted/std_array/detail/begin_impl.hpp create mode 100644 boost/fusion/adapted/std_array/detail/category_of_impl.hpp create mode 100644 boost/fusion/adapted/std_array/detail/end_impl.hpp create mode 100644 boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp create mode 100644 boost/fusion/adapted/std_array/detail/is_view_impl.hpp create mode 100644 boost/fusion/adapted/std_array/detail/size_impl.hpp create mode 100644 boost/fusion/adapted/std_array/detail/value_at_impl.hpp create mode 100644 boost/fusion/adapted/std_array/std_array_iterator.hpp create mode 100644 boost/fusion/adapted/std_array/tag_of.hpp create mode 100644 libs/fusion/test/Jamfile create mode 100644 libs/fusion/test/sequence/CMakeLists.txt create mode 100644 libs/fusion/test/sequence/std_array.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f288c69f --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +# Build directories +_build* +build* diff --git a/Jamroot b/Jamroot new file mode 100644 index 00000000..e9815173 --- /dev/null +++ b/Jamroot @@ -0,0 +1,27 @@ +# +# Copyright (C) 2013 Mateusz Loskot +# +# 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) +# +import os ; + +local BOOST_ROOT = [ os.environ BOOST_ROOT ] ; +if $(BOOST_ROOT) +{ + use-project /boost : $(BOOST_ROOT) ; +} + +# Declare project +project boost_fusion_std_array + : + requirements + . + clang:-std=c++11 + gcc:-std=c++0x + gcc:multi + gcc:-ftemplate-depth=300 + msvc:/wd4996 + /boost//headers + ; diff --git a/README.md b/README.md new file mode 100644 index 00000000..ace40f99 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +Boost.Fusion extension for std::array +===================================== + +An attempt to adapt ```std::array``` for Boost.Fusion. + +The implementation is functional and passes the same test as adapted Boost.Array. + +However, there is a problem with ADL and range-based access to the sequence +which is a well-known issue: + +* [Fusion begin/end ADL issues with C++0x range-based for](http://lists.boost.org/Archives/boost/2010/12/index.php) +* Boost ticket: [https://svn.boost.org/trac/boost/ticket/4028 fusion::begin and fusion::end lead to problems with ADL-based begin and end functions for ranges] +* Boost ticket: [https://svn.boost.org/trac/boost/ticket/8241 Treat std::array as a Fusion sequence] diff --git a/boost/fusion/adapted/std_array/detail/array_size.hpp b/boost/fusion/adapted/std_array/detail/array_size.hpp new file mode 100644 index 00000000..2f839404 --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/array_size.hpp @@ -0,0 +1,25 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + + 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_STD_ARRAY_ARRAY_SIZE_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_ARRAY_SIZE_01062013_1700 + +#include +#include + +namespace boost { namespace fusion +{ + namespace extension + { + template + struct std_array_size; + + template class Array, typename T, std::size_t N> + struct std_array_size> : std::integral_constant {}; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/detail/at_impl.hpp b/boost/fusion/adapted/std_array/detail/at_impl.hpp new file mode 100644 index 00000000..6086264a --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/at_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_AT_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_AT_IMPL_01062013_1700 + +#include + +#include + +namespace boost { namespace fusion { + + struct std_array_tag; + + namespace extension + { + template + struct at_impl; + + template<> + struct at_impl + { + template + struct apply + { + typedef typename mpl::if_< + is_const, + typename Sequence::const_reference, + typename Sequence::reference>::type type; + + static type + call(Sequence& seq) + { + return seq[N::value]; + } + }; + }; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/detail/begin_impl.hpp b/boost/fusion/adapted/std_array/detail/begin_impl.hpp new file mode 100644 index 00000000..c84082e3 --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/begin_impl.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_BEGIN_OF_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_BEGIN_OF_IMPL_01062013_1700 + +#include + +namespace boost { namespace fusion { + + struct std_array_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef std_array_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/detail/category_of_impl.hpp b/boost/fusion/adapted/std_array/detail/category_of_impl.hpp new file mode 100644 index 00000000..b5fa0935 --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/category_of_impl.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_CATEGORY_OF_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_CATEGORY_OF_IMPL_01062013_1700 + +#include + +namespace boost { namespace fusion { + + struct std_array_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 diff --git a/boost/fusion/adapted/std_array/detail/end_impl.hpp b/boost/fusion/adapted/std_array/detail/end_impl.hpp new file mode 100644 index 00000000..b7b789ef --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/end_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_END_OF_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_END_OF_IMPL_01062013_1700 + +#include +#include +#include + +namespace boost { namespace fusion { + + struct std_array_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 = std_array_size::value; + typedef std_array_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp b/boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp new file mode 100644 index 00000000..8308e838 --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/is_sequence_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_IS_SEQUENCE_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_IS_SEQUENCE_IMPL_01062013_1700 + +#include + +namespace boost { namespace fusion { + + struct std_array_tag; + + namespace extension + { + template + struct is_sequence_impl; + + template<> + struct is_sequence_impl + { + template + struct apply : mpl::true_ {}; + }; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/detail/is_view_impl.hpp b/boost/fusion/adapted/std_array/detail/is_view_impl.hpp new file mode 100644 index 00000000..89cd04cf --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/is_view_impl.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_IS_VIEW_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_IS_VIEW_IMPL_01062013_1700 + +#include + +namespace boost { namespace fusion +{ + struct std_array_tag; + + namespace extension + { + template + struct is_view_impl; + + template<> + struct is_view_impl + { + template + struct apply : mpl::false_ + {}; + }; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/detail/size_impl.hpp b/boost/fusion/adapted/std_array/detail/size_impl.hpp new file mode 100644 index 00000000..7df51b2a --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/size_impl.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_SIZE_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_SIZE_IMPL_01062013_1700 + +#include +#include + +namespace boost { namespace fusion { + + struct std_array_tag; + + namespace extension + { + template + struct size_impl; + + template<> + struct size_impl + { + template + struct apply + : mpl::int_ + < + std_array_size + < + typename remove_const::type + >::value + > + {}; + }; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/detail/value_at_impl.hpp b/boost/fusion/adapted/std_array/detail/value_at_impl.hpp new file mode 100644 index 00000000..3d7871a7 --- /dev/null +++ b/boost/fusion/adapted/std_array/detail/value_at_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_VALUE_AT_IMPL_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_VALUE_AT_IMPL_01062013_1700 + +namespace boost { namespace fusion { + + struct std_array_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply + { + typedef typename Sequence::value_type type; + }; + }; + } +}} + +#endif diff --git a/boost/fusion/adapted/std_array/std_array_iterator.hpp b/boost/fusion/adapted/std_array/std_array_iterator.hpp new file mode 100644 index 00000000..f09b81e1 --- /dev/null +++ b/boost/fusion/adapted/std_array/std_array_iterator.hpp @@ -0,0 +1,108 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_ARRAY_ITERATOR_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_ARRAY_ITERATOR_01062013_1700 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct random_access_traversal_tag; + + template + struct std_array_iterator + : iterator_facade, random_access_traversal_tag> + { + BOOST_MPL_ASSERT_RELATION(Pos, >=, 0); + BOOST_MPL_ASSERT_RELATION(Pos, <=, static_cast(extension::std_array_size::value)); + + typedef mpl::int_ index; + typedef Array array_type; + + std_array_iterator(Array& a) + : array(a) {} + + Array& array; + + template + struct value_of + { + typedef typename Iterator::array_type array_type; + typedef typename array_type::value_type type; + }; + + template + struct deref + { + typedef typename Iterator::array_type array_type; + typedef typename + mpl::if_< + is_const + , typename array_type::const_reference + , typename array_type::reference + >::type + type; + + static type + call(Iterator const & it) + { + return it.array[Iterator::index::value]; + } + }; + + template + struct advance + { + typedef typename Iterator::index index; + typedef typename Iterator::array_type array_type; + typedef std_array_iterator type; + + static type + call(Iterator const& i) + { + return type(i.array); + } + }; + + template + struct next : advance > {}; + + template + struct prior : advance > {}; + + template + struct distance : mpl::minus + { + typedef typename + mpl::minus< + typename I2::index, typename I1::index + >::type + type; + + static type + call(I1 const&, I2 const&) + { + return type(); + } + }; + + private: + + std_array_iterator& operator=(std_array_iterator const&); + }; +}} + +#endif diff --git a/boost/fusion/adapted/std_array/tag_of.hpp b/boost/fusion/adapted/std_array/tag_of.hpp new file mode 100644 index 00000000..c0e1c089 --- /dev/null +++ b/boost/fusion/adapted/std_array/tag_of.hpp @@ -0,0 +1,58 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY_TAG_OF_01062013_1700) +#define BOOST_FUSION_STD_ARRAY_TAG_OF_01062013_1700 + +#include + +#include + +namespace std +{ + template + class array; +} + +namespace boost { namespace fusion +{ + struct std_array_tag; + struct fusion_sequence_tag; + + namespace traits + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + struct tag_of, void > +#else + struct tag_of > +#endif + { + typedef std_array_tag type; + }; + } +}} + +namespace boost { namespace mpl +{ + template + struct sequence_tag; + + template + struct sequence_tag > + { + typedef fusion::fusion_sequence_tag type; + }; + + template + struct sequence_tag const> + { + typedef fusion::fusion_sequence_tag type; + }; +}} + +#endif diff --git a/libs/fusion/test/Jamfile b/libs/fusion/test/Jamfile new file mode 100644 index 00000000..73ac6c08 --- /dev/null +++ b/libs/fusion/test/Jamfile @@ -0,0 +1,22 @@ +##============================================================================== +# Copyright (c) 2013 Mateusz Loskot +# Copyright (c) 2003-2006 Joel de Guzman +# +# Use, modification and distribution is subject to 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) +#============================================================================== +# bring in rules for testing +import testing ; + +project + : requirements + ; + +{ + test-suite fusion_std_array : + + [ run sequence/std_array.cpp : : : : ] + + ; +} diff --git a/libs/fusion/test/sequence/CMakeLists.txt b/libs/fusion/test/sequence/CMakeLists.txt new file mode 100644 index 00000000..e948818c --- /dev/null +++ b/libs/fusion/test/sequence/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required (VERSION 2.8) +project(boost_fusion_std_array) + +if(MSVC) + list(APPEND CMAKE_CXX_FLAGS /Za) +else() +list(APPEND CMAKE_CXX_FLAGS -pedantic -Wall) +if(CMAKE_COMPILER_IS_GNUCXX) + list(APPEND CMAKE_CXX_FLAGS -std=c++0x) +elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR "${CMAKE_CXX_COMPILER}" MATCHES "clang") + list(APPEND CMAKE_CXX_FLAGS -std=c++11) +endif() +endif() + +string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +find_package(Boost 1.54) +if (NOT Boost_FOUND) + message(FATAL_ERROR "Cannot find Boost") +endif() +include_directories(${Boost_INCLUDE_DIRS}) + +add_executable(std_array std_array.cpp) diff --git a/libs/fusion/test/sequence/std_array.cpp b/libs/fusion/test/sequence/std_array.cpp new file mode 100644 index 00000000..54d3713c --- /dev/null +++ b/libs/fusion/test/sequence/std_array.cpp @@ -0,0 +1,42 @@ +// +// Copyright (C) 2013 Mateusz Loskot +// +// 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) +// +#pragma warning(disable:4180) +#include + +#include +#include + +#include +#include +#include +#include + +#include + +int main() +{ + using namespace boost::fusion; + typedef std::array array_type; + + + BOOST_MPL_ASSERT((traits::is_sequence)); + BOOST_MPL_ASSERT_NOT((traits::is_view)); + + array_type arr = {{1,2,3}}; + + BOOST_TEST(*boost::fusion::begin(arr) == 1); + BOOST_TEST(*boost::fusion::next(boost::fusion::begin(arr)) == 2); + BOOST_TEST(*advance_c<2>(boost::fusion::begin(arr)) == 3); + BOOST_TEST(prior(boost::fusion::next(boost::fusion::begin(arr))) == boost::fusion::begin(arr)); + BOOST_TEST(*prior(boost::fusion::end(arr)) == 3); + BOOST_TEST(at_c<2>(arr) == 3); + BOOST_TEST(size(arr) == 3); + BOOST_TEST(distance(boost::fusion::begin(arr), boost::fusion::end(arr)) == 3); + + return boost::report_errors(); +} From a49eb03483aae1a812186253b233a785e0a67039 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Tue, 2 Jul 2013 13:31:37 +0100 Subject: [PATCH 02/32] Fix links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ace40f99..3bd92343 100644 --- a/README.md +++ b/README.md @@ -9,5 +9,5 @@ However, there is a problem with ADL and range-based access to the sequence which is a well-known issue: * [Fusion begin/end ADL issues with C++0x range-based for](http://lists.boost.org/Archives/boost/2010/12/index.php) -* Boost ticket: [https://svn.boost.org/trac/boost/ticket/4028 fusion::begin and fusion::end lead to problems with ADL-based begin and end functions for ranges] -* Boost ticket: [https://svn.boost.org/trac/boost/ticket/8241 Treat std::array as a Fusion sequence] +* Boost ticket: [fusion::begin and fusion::end lead to problems with ADL-based begin and end functions for ranges](https://svn.boost.org/trac/boost/ticket/402) +* Boost ticket: [Treat std::array as a Fusion sequence](https://svn.boost.org/trac/boost/ticket/8241) From 6c130b9e44ac922cf5ccde3e104cd9fc5fd4751f Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Tue, 2 Jul 2013 13:38:38 +0100 Subject: [PATCH 03/32] Fix ticket number --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3bd92343..bd582eb7 100644 --- a/README.md +++ b/README.md @@ -9,5 +9,5 @@ However, there is a problem with ADL and range-based access to the sequence which is a well-known issue: * [Fusion begin/end ADL issues with C++0x range-based for](http://lists.boost.org/Archives/boost/2010/12/index.php) -* Boost ticket: [fusion::begin and fusion::end lead to problems with ADL-based begin and end functions for ranges](https://svn.boost.org/trac/boost/ticket/402) +* Boost ticket: [fusion::begin and fusion::end lead to problems with ADL-based begin and end functions for ranges](https://svn.boost.org/trac/boost/ticket/4028) * Boost ticket: [Treat std::array as a Fusion sequence](https://svn.boost.org/trac/boost/ticket/8241) From 6849e31db08dcd78a991c4efe12c1832e45ed833 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Thu, 4 Jul 2013 00:56:53 +0100 Subject: [PATCH 04/32] Ignore bin directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f288c69f..2e29b503 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,6 @@ *.a # Build directories +bin _build* build* From cccbc785d655c182832007c06debe7ef187d0672 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Thu, 4 Jul 2013 00:57:22 +0100 Subject: [PATCH 05/32] Include missing array_size.hpp --- boost/fusion/adapted/std_array/std_array_iterator.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/boost/fusion/adapted/std_array/std_array_iterator.hpp b/boost/fusion/adapted/std_array/std_array_iterator.hpp index f09b81e1..f52c7c71 100644 --- a/boost/fusion/adapted/std_array/std_array_iterator.hpp +++ b/boost/fusion/adapted/std_array/std_array_iterator.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { namespace fusion { From abb15d1158618fa71312307567a23c3c17f296ec Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Thu, 4 Jul 2013 00:57:44 +0100 Subject: [PATCH 06/32] Add all-in-one header for std_array --- boost/fusion/adapted/std_array.hpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 boost/fusion/adapted/std_array.hpp diff --git a/boost/fusion/adapted/std_array.hpp b/boost/fusion/adapted/std_array.hpp new file mode 100644 index 00000000..64ae6460 --- /dev/null +++ b/boost/fusion/adapted/std_array.hpp @@ -0,0 +1,23 @@ +/*============================================================================= + Copyright (c) 2013 Mateusz Loskot + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_STD_ARRAY__01062013_1700) +#define BOOST_FUSION_STD_ARRAY__01062013_1700 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif From 789b86fd6c08cf6bab24c21b9a3608fa23a3110c Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Fri, 5 Jul 2013 23:46:46 +0100 Subject: [PATCH 07/32] Wrap #pragma warning BOOST_MSVC --- libs/fusion/test/sequence/std_array.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/fusion/test/sequence/std_array.cpp b/libs/fusion/test/sequence/std_array.cpp index 54d3713c..c96899f7 100644 --- a/libs/fusion/test/sequence/std_array.cpp +++ b/libs/fusion/test/sequence/std_array.cpp @@ -5,7 +5,9 @@ // (See accompanying file LICENSE_1_0.txt or copy // at http://www.boost.org/LICENSE_1_0.txt) // +#ifdef BOOST_MSVC #pragma warning(disable:4180) +#endif #include #include From 17928ac3856db67f170c30490338584fa7fa1881 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Fri, 5 Jul 2013 23:47:48 +0100 Subject: [PATCH 08/32] Call build-project to build test from top dir --- Jamroot | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Jamroot b/Jamroot index e9815173..ff508215 100644 --- a/Jamroot +++ b/Jamroot @@ -25,3 +25,5 @@ project boost_fusion_std_array msvc:/wd4996 /boost//headers ; + +build-project libs/fusion/test ; From 1e2841c68385d46bb3c7fcbdeeff01f59482e431 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Fri, 5 Jul 2013 23:51:23 +0100 Subject: [PATCH 09/32] Add comment on conflicts with C++11 range access --- libs/fusion/test/sequence/std_array.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/fusion/test/sequence/std_array.cpp b/libs/fusion/test/sequence/std_array.cpp index c96899f7..49040bfc 100644 --- a/libs/fusion/test/sequence/std_array.cpp +++ b/libs/fusion/test/sequence/std_array.cpp @@ -22,6 +22,10 @@ int main() { + // See README.md for explanation on qualified names below + // C++11 range access interferes with Boost.Fusion: + // error: call to 'begin' is ambiguous + using namespace boost::fusion; typedef std::array array_type; From 53a1a74a10211ed0ae09a8a7aefd76d6c617dd4d Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Sat, 6 Jul 2013 00:55:58 +0100 Subject: [PATCH 10/32] Refine the ADL comment --- libs/fusion/test/sequence/std_array.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/fusion/test/sequence/std_array.cpp b/libs/fusion/test/sequence/std_array.cpp index 49040bfc..f445ca1d 100644 --- a/libs/fusion/test/sequence/std_array.cpp +++ b/libs/fusion/test/sequence/std_array.cpp @@ -23,7 +23,7 @@ int main() { // See README.md for explanation on qualified names below - // C++11 range access interferes with Boost.Fusion: + // C++0x/11 range access interferes with Boost.Fusion interface: // error: call to 'begin' is ambiguous using namespace boost::fusion; From 31b1ee7f730afc9a3c5c3428717a5af8f55e9776 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Sat, 6 Jul 2013 00:57:08 +0100 Subject: [PATCH 11/32] Link N3257 paper and the latest Boost thread --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bd582eb7..b3e5e4b7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,10 @@ Boost.Fusion extension for std::array An attempt to adapt ```std::array``` for Boost.Fusion. -The implementation is functional and passes the same test as adapted Boost.Array. +The implementation is functional and passes the same test as adapted Boost.Array. + +Proposal thread on the Boost mailing list: +[Adapter for std::array](http://lists.boost.org/Archives/boost/2013/07/205045.php). However, there is a problem with ADL and range-based access to the sequence which is a well-known issue: @@ -11,3 +14,9 @@ which is a well-known issue: * [Fusion begin/end ADL issues with C++0x range-based for](http://lists.boost.org/Archives/boost/2010/12/index.php) * Boost ticket: [fusion::begin and fusion::end lead to problems with ADL-based begin and end functions for ranges](https://svn.boost.org/trac/boost/ticket/4028) * Boost ticket: [Treat std::array as a Fusion sequence](https://svn.boost.org/trac/boost/ticket/8241) + +See also: + +* N3257=11-0027 Jonathan Wakely and Bjarne Stroustrup: +[Range-based for statements and ADL](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3257.pdf). +Option 5 was chosen for C++11. From 0e24ec0a85e3ad5fc75433c9f73bda7eeed9f3d7 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Sat, 6 Jul 2013 01:03:18 +0100 Subject: [PATCH 12/32] Format --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b3e5e4b7..e6ec72f4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ An attempt to adapt ```std::array``` for Boost.Fusion. The implementation is functional and passes the same test as adapted Boost.Array. Proposal thread on the Boost mailing list: -[Adapter for std::array](http://lists.boost.org/Archives/boost/2013/07/205045.php). +[[fusion] Adapter for std::array](http://lists.boost.org/Archives/boost/2013/07/205045.php). However, there is a problem with ADL and range-based access to the sequence which is a well-known issue: From e12f59ebf2040cf49623334191f743e9909e7844 Mon Sep 17 00:00:00 2001 From: Mateusz Loskot Date: Sun, 7 Jul 2013 23:17:42 +0100 Subject: [PATCH 13/32] Add Jonathan Wakely's opinion from Boost ml --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index e6ec72f4..e8719c37 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,8 @@ See also: * N3257=11-0027 Jonathan Wakely and Bjarne Stroustrup: [Range-based for statements and ADL](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3257.pdf). Option 5 was chosen for C++11. + +* [Jonathan Wakely's review](http://lists.boost.org/Archives/boost/2013/07/205064.php) of the issue regarding the Boost.Fusion adaptor for ```std::string```: + > The standard was changed to *not* use unqualified begin/end when the type has begin/end members, because +when there are multiple "greedy" overloads that can be found by ADL there is no simple way to prevent ambiguity. So I agree that your +best option might be to avoid those unqualified calls. From a2874ea5fe76419857521a7ae60716e19854d00c Mon Sep 17 00:00:00 2001 From: alfC Date: Tue, 4 Feb 2014 11:33:06 -0800 Subject: [PATCH 14/32] Changed static assertion that checks array size to a more standard way. This avoids an obscure error involving `extension::std_array_size` --- boost/fusion/adapted/std_array/std_array_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/fusion/adapted/std_array/std_array_iterator.hpp b/boost/fusion/adapted/std_array/std_array_iterator.hpp index f52c7c71..29584512 100644 --- a/boost/fusion/adapted/std_array/std_array_iterator.hpp +++ b/boost/fusion/adapted/std_array/std_array_iterator.hpp @@ -28,7 +28,7 @@ namespace boost { namespace fusion : iterator_facade, random_access_traversal_tag> { BOOST_MPL_ASSERT_RELATION(Pos, >=, 0); - BOOST_MPL_ASSERT_RELATION(Pos, <=, static_cast(extension::std_array_size::value)); + BOOST_MPL_ASSERT_RELATION(Pos, <=, std::tuple_size::value); typedef mpl::int_ index; typedef Array array_type; From da294ebc6dcc852f7e365269a09de56a7d0f2949 Mon Sep 17 00:00:00 2001 From: correaa Date: Fri, 7 Feb 2014 22:24:29 -0800 Subject: [PATCH 15/32] Update tag_of.hpp avoid mismatched-tags warning in clang --- boost/fusion/adapted/std_array/tag_of.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/fusion/adapted/std_array/tag_of.hpp b/boost/fusion/adapted/std_array/tag_of.hpp index c0e1c089..f307be2d 100644 --- a/boost/fusion/adapted/std_array/tag_of.hpp +++ b/boost/fusion/adapted/std_array/tag_of.hpp @@ -15,7 +15,7 @@ namespace std { template - class array; + struct array; } namespace boost { namespace fusion From 79d8e9d11c07099bdf1db0724e8fb1ee92e98920 Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Tue, 31 May 2016 13:43:54 -0400 Subject: [PATCH 16/32] Added to nested tests, and fixed C++11 vector copy-from-sequence --- .../boost/fusion/container/vector/vector.hpp | 31 ++++++---- test/sequence/nest.hpp | 59 +++++++++++++++++++ 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/include/boost/fusion/container/vector/vector.hpp b/include/boost/fusion/container/vector/vector.hpp index 65bffd0b..a302bc93 100644 --- a/include/boost/fusion/container/vector/vector.hpp +++ b/include/boost/fusion/container/vector/vector.hpp @@ -33,13 +33,14 @@ #include #include #include +#include #include #include #include -#include #include +#include +#include #include -#include #include #include #include @@ -66,15 +67,20 @@ namespace boost { namespace fusion template struct pure : remove_cv::type> {}; - template ::value> - struct is_convertible_to_first - : boost::is_convertible::type> - {}; + template + struct can_convert : mpl::false_ {}; - template - struct is_convertible_to_first - : mpl::false_ - {}; + template + struct can_convert< + Sequence + , This + , typename enable_if>::type + > : mpl::equal_to< + fusion::result_of::size + , fusion::result_of::size + > + { + }; template BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED @@ -90,9 +96,8 @@ namespace boost { namespace fusion BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED inline from_sequence< typename lazy_enable_if_c< - (traits::is_sequence::type>::value && - !is_same::type>::value && - !is_convertible_to_first::value) + (!is_same::type>::value && + can_convert::type, This>::value) , make_indices_from_seq >::type > diff --git a/test/sequence/nest.hpp b/test/sequence/nest.hpp index e8087320..1f677109 100644 --- a/test/sequence/nest.hpp +++ b/test/sequence/nest.hpp @@ -7,6 +7,43 @@ #include #include +#include +#include +#include + +template class As> +void test_from_sequence_rvalue() +{ + typename As::type dst((C())); + (void)dst; +} + +template class As> +void test_from_sequence_const_lvalue() +{ + C src; + typename As::type dst(src); + (void)dst; +} + +template class As> +void test_from_sequence_lvalue() +{ + const C src; + typename As::type dst(src); + (void)dst; +} + +template class As> +void test_from_sequence() +{ +// the following tests do not work in all cases for C++03 +#if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) + test_from_sequence_rvalue(); + test_from_sequence_const_lvalue(); + test_from_sequence_lvalue(); +#endif +} template void test_copy() @@ -29,6 +66,10 @@ void test_move() template void test_all() { +// as_deque and as_list do not work in C++03 or C++11 mode +// test_from_sequence(); +// test_from_sequence(); + test_from_sequence(); test_copy(); #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) test_move(); @@ -54,5 +95,23 @@ test() test_all, int> >(); test_all > >(); test_all, float> >(); + + test_all, FUSION_SEQUENCE<> > >(); + test_all, FUSION_SEQUENCE<> > >(); + test_all, FUSION_SEQUENCE > >(); + test_all< + FUSION_SEQUENCE, FUSION_SEQUENCE > + >(); + test_all< + FUSION_SEQUENCE, FUSION_SEQUENCE > + >(); + test_all< + FUSION_SEQUENCE, FUSION_SEQUENCE > + >(); + test_all< + FUSION_SEQUENCE< + FUSION_SEQUENCE, FUSION_SEQUENCE + > + >(); } From 55150a7fa675235af68e43cd18cce2f58d5d36ce Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Fri, 22 Jul 2016 18:52:20 -0400 Subject: [PATCH 17/32] Add DISABLE_VARIADIC_VECTOR and SFINAE for c++11 tuple element construction --- .../fusion/container/vector/detail/config.hpp | 1 + include/boost/fusion/support/detail/and.hpp | 35 +++++ include/boost/fusion/tuple/tuple.hpp | 23 +++- include/boost/fusion/tuple/tuple_fwd.hpp | 1 + test/Jamfile | 15 +++ test/sequence/tuple_construction.cpp | 28 ++++ test/sequence/tuple_traits.cpp | 123 ++++++++++++++++++ test/support/and.cpp | 33 +++++ 8 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 include/boost/fusion/support/detail/and.hpp create mode 100644 test/sequence/tuple_traits.cpp create mode 100644 test/support/and.cpp diff --git a/include/boost/fusion/container/vector/detail/config.hpp b/include/boost/fusion/container/vector/detail/config.hpp index 84f4605d..a80fd69a 100644 --- a/include/boost/fusion/container/vector/detail/config.hpp +++ b/include/boost/fusion/container/vector/detail/config.hpp @@ -15,6 +15,7 @@ || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \ || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) \ || defined(BOOST_NO_CXX11_DECLTYPE)) \ + || defined(BOOST_FUSION_DISABLE_VARIADIC_VECTOR) \ || (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)) # if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) # undef BOOST_FUSION_HAS_VARIADIC_VECTOR diff --git a/include/boost/fusion/support/detail/and.hpp b/include/boost/fusion/support/detail/and.hpp new file mode 100644 index 00000000..8560f344 --- /dev/null +++ b/include/boost/fusion/support/detail/and.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2016 Lee Clagett + + 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 FUSION_AND_07152016_1625 +#define FUSION_AND_07152016_1625 + +#include +#include + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#error fusion::detail::and_ requires variadic templates +#endif + +namespace boost { namespace fusion { namespace detail { + template + struct and_impl : false_type {}; + + template + struct and_impl...> : true_type {}; + + /* fusion::detail::and_ differs from mpl::and_ in the following ways: + - The empty set is valid and returns true + - A single element set is valid and returns the identity + - There is no upper bound on the set size + - The conditions are evaluated at once, and are not short-circuited. This + reduces instantations when returning true; the implementation is not + recursive. */ + template + struct and_ : and_impl...> {}; +}}} + +#endif // FUSION_AND_07152016_1625 diff --git a/include/boost/fusion/tuple/tuple.hpp b/include/boost/fusion/tuple/tuple.hpp index 6ee21f56..606e1694 100644 --- a/include/boost/fusion/tuple/tuple.hpp +++ b/include/boost/fusion/tuple/tuple.hpp @@ -20,12 +20,15 @@ /////////////////////////////////////////////////////////////////////////////// // C++11 interface /////////////////////////////////////////////////////////////////////////////// +#include #include #include #include #include #include #include +#include +#include #include namespace boost { namespace fusion @@ -49,13 +52,29 @@ namespace boost { namespace fusion tuple(tuple&& other) : base_type(std::move(other)) {} - template + template < + typename ...U + , typename = typename boost::enable_if_c<( + fusion::detail::and_...>::value && + sizeof...(U) >= 1 + )>::type + > /*BOOST_CONSTEXPR*/ BOOST_FUSION_GPU_ENABLED explicit tuple(U&&... args) : base_type(std::forward(args)...) {} - template + template + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + tuple(std::pair const& other) + : base_type(other.first, other.second) {} + + template + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + tuple(std::pair&& other) + : base_type(std::move(other.first), std::move(other.second)) {} + + template BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED tuple& operator=(U&& rhs) { diff --git a/include/boost/fusion/tuple/tuple_fwd.hpp b/include/boost/fusion/tuple/tuple_fwd.hpp index b763acd5..f3e8deb0 100644 --- a/include/boost/fusion/tuple/tuple_fwd.hpp +++ b/include/boost/fusion/tuple/tuple_fwd.hpp @@ -12,6 +12,7 @@ #include #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) \ + || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ || (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)) # if defined(BOOST_FUSION_HAS_VARIADIC_TUPLE) # undef BOOST_FUSION_HAS_VARIADIC_TUPLE diff --git a/test/Jamfile b/test/Jamfile index 8f290165..7e5e4186 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -131,6 +131,20 @@ project [ run sequence/tuple_nest.cpp : : : : ] [ run sequence/tuple_hash.cpp : : : : ] [ run sequence/tuple_tie.cpp : : : : ] + [ + run sequence/tuple_traits.cpp + : + : + : + : sequence/tuple_traits/maybe_variadic_vector + ] + [ + run sequence/tuple_traits.cpp + : + : + : BOOST_FUSION_DISABLE_VARIADIC_VECTOR + : sequence/tuple_traits/no_variadic_vector + ] [ run sequence/transform_view.cpp : : : : ] [ run sequence/vector_comparison.cpp : : : : ] [ run sequence/vector_construction.cpp : : : : ] @@ -197,6 +211,7 @@ project [ compile support/pair_vector.cpp : : : : ] [ compile support/pair_nest.cpp : : : : ] [ compile support/index_sequence.cpp : : : : ] + [ compile support/and.cpp : : : : ] # [ compile-fail xxx.cpp : : : : ] diff --git a/test/sequence/tuple_construction.cpp b/test/sequence/tuple_construction.cpp index 044701c4..12772027 100644 --- a/test/sequence/tuple_construction.cpp +++ b/test/sequence/tuple_construction.cpp @@ -13,9 +13,37 @@ #define FUSION_AT get #include "construction.hpp" +// Bug in C++03 tuple? Cannot construct from a std::pair without including +// std::pair fusion adaption +#if !defined(BOOST_FUSION_HAS_VARIADIC_TUPLE) +# include +#endif + +struct test_conversion +{ + test_conversion(int value) : value_(value) {} + + int value_; +}; + int main() { test(); + + { + using namespace boost::fusion; + const tuple instance(std::pair(1, 9)); + BOOST_TEST(boost::fusion::get<0>(instance) == 1); + BOOST_TEST(boost::fusion::get<1>(instance).value_ == 9); + } + { + using namespace boost::fusion; + const std::pair init(16, 4); + const tuple instance(init); + BOOST_TEST(boost::fusion::get<0>(instance) == 16); + BOOST_TEST(boost::fusion::get<1>(instance).value_ == 4); + } + return boost::report_errors(); } diff --git a/test/sequence/tuple_traits.cpp b/test/sequence/tuple_traits.cpp new file mode 100644 index 00000000..e13a0076 --- /dev/null +++ b/test/sequence/tuple_traits.cpp @@ -0,0 +1,123 @@ +/*============================================================================= + Copyright (c) 2016 Lee Clagett + + 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 + +struct test_conversion +{ + test_conversion(int) {} +}; + +struct test_no_conversion +{ + explicit test_no_conversion(int) {} +}; + +/* Some construction differences in fusion::tuple from std::tuple: + - Construction from elements cannot call an explicit constructor. + - There is no implicit construction from elements. + - Construction from std::pair is _enabled_ when tuple is not of size 2. + - Construction from tuple is _enabled_ when destination tuple is of + different size. + - Implicit construction from std::pair can call explicit constructors on + elements. + - Implicit construction from tuple can call explicit constructors on + elements. + + These differences are historical. Matching the behavior of std::tuple + could break existing code, however, switching to fusion::vector would + restore the historical behavior. */ +int +main() { + { + using namespace boost; + using namespace boost::fusion; + + BOOST_TEST(!(is_convertible >::value)); + BOOST_TEST(!(is_convertible >::value)); + + BOOST_TEST(!(is_convertible< int, tuple >::value)); + BOOST_TEST(!(is_convertible< int&, tuple >::value)); + BOOST_TEST(!(is_convertible< vector, tuple >::value)); + BOOST_TEST(!(is_convertible< vector&, tuple >::value)); + + BOOST_TEST(!(is_convertible >::value)); + BOOST_TEST(!(is_convertible >::value)); + } + +// is_constructible has some restrictions ... +#if !(defined(BOOST_NO_CXX11_DECLTYPE) || defined(BOOST_NO_CXX11_TEMPLATES) || \ + defined(BOOST_NO_SFINAE_EXPR)) + { + using namespace boost; + using namespace boost::fusion; + + BOOST_TEST((is_constructible< tuple<> >::value)); + BOOST_TEST(!(is_constructible, int>::value)); + BOOST_TEST(!(is_constructible, int&>::value)); + + BOOST_TEST((is_constructible< tuple >::value)); + BOOST_TEST((is_constructible, int>::value)); + BOOST_TEST((is_constructible, int&>::value)); + BOOST_TEST((is_constructible, int>::value)); + BOOST_TEST((is_constructible, int&>::value)); + BOOST_TEST(!(is_constructible, int>::value)); + BOOST_TEST(!(is_constructible, int&>::value)); + BOOST_TEST(!(is_constructible< tuple, vector >::value)); + BOOST_TEST(!(is_constructible, vector&>::value)); + BOOST_TEST(!(is_constructible, int, int>::value)); + BOOST_TEST(!(is_constructible, int&, int&>::value)); + + BOOST_TEST((is_constructible< tuple >::value)); + BOOST_TEST((is_constructible, int, int>::value)); + BOOST_TEST((is_constructible, int&, int&>::value)); + BOOST_TEST(( + is_constructible< + tuple + , int + , int + >::value + )); + BOOST_TEST(( + is_constructible< + tuple + , int& + , int& + >::value + )); + BOOST_TEST(!( + is_constructible< + tuple + , int + , int + >::value + )); + BOOST_TEST(!( + is_constructible< + tuple + , int& + , int& + >::value + )); +#if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) + // C++03 fusion::tuple has constructors that can never be used + BOOST_TEST(!(is_constructible, int>::value)); + BOOST_TEST(!(is_constructible, int&>::value)); +#endif + BOOST_TEST(!(is_constructible, int, int, int>::value)); + BOOST_TEST(!( + is_constructible, int&, int&, int&>::value + )); + } +#endif + + return boost::report_errors(); +} diff --git a/test/support/and.cpp b/test/support/and.cpp new file mode 100644 index 00000000..99ecd9f4 --- /dev/null +++ b/test/support/and.cpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2016 Lee Clagett + 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 + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#include +#include +#include +#include + +int main() { + using namespace boost; + using namespace boost::fusion::detail; + + BOOST_TEST((and_<>::value)); + BOOST_TEST(!(and_::value)); + BOOST_TEST((and_::value)); + BOOST_TEST(!(and_::value)); + BOOST_TEST((and_::value)); + BOOST_TEST(!(and_::value)); + BOOST_TEST((and_::value)); + BOOST_TEST((and_::value)); + + return boost::report_errors(); +} + +#endif + From 5906d9c31698048f1542ef5121eab93154c3c8bc Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Sun, 21 Aug 2016 16:59:04 -0400 Subject: [PATCH 18/32] Make C++11 fusion::vector more consistent with C++03 fusion::vector - Construct from elements is enabled iff each argument is_convertible to corresponding element. - Construct from sequence is enabled iff the single argument is a fusion sequence. - C++11 vector and tuple also disable construct from sequence that are shorter than the destination. C++03 gives incorrect is_convertible responses in this situation and fails to compile if that constructor is used; C++11 can have instantation errors in and_...> without the additional check. - C++11 tuple and vector support truncation conversion and assignment like all other sequences. --- .../fusion/container/vector/detail/config.hpp | 1 + .../boost/fusion/container/vector/vector.hpp | 174 ++++---- include/boost/fusion/tuple/tuple.hpp | 16 +- include/boost/fusion/tuple/tuple_fwd.hpp | 1 - test/Jamfile | 20 +- test/sequence/conversion.hpp | 320 +++++++++++++++ test/sequence/copy.hpp | 74 +++- test/sequence/deque_copy.cpp | 24 +- test/sequence/deque_nest.cpp | 28 +- test/sequence/fixture.hpp | 216 ++++++++++ test/sequence/list_copy.cpp | 2 +- test/sequence/list_nest.cpp | 21 +- test/sequence/nest.hpp | 380 ++++++++++++++---- test/sequence/traits.hpp | 251 ++++++++++++ test/sequence/tuple_conversion.cpp | 51 +++ test/sequence/tuple_copy.cpp | 2 +- test/sequence/tuple_nest.cpp | 20 +- test/sequence/tuple_traits.cpp | 129 +++--- test/sequence/vector_conversion.cpp | 19 + test/sequence/vector_copy.cpp | 2 +- test/sequence/vector_nest.cpp | 4 +- test/sequence/vector_traits.cpp | 32 ++ 22 files changed, 1504 insertions(+), 283 deletions(-) create mode 100644 test/sequence/conversion.hpp create mode 100644 test/sequence/fixture.hpp create mode 100644 test/sequence/traits.hpp create mode 100644 test/sequence/tuple_conversion.cpp create mode 100644 test/sequence/vector_conversion.cpp create mode 100644 test/sequence/vector_traits.cpp diff --git a/include/boost/fusion/container/vector/detail/config.hpp b/include/boost/fusion/container/vector/detail/config.hpp index a80fd69a..2a7aea64 100644 --- a/include/boost/fusion/container/vector/detail/config.hpp +++ b/include/boost/fusion/container/vector/detail/config.hpp @@ -15,6 +15,7 @@ || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) \ || defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) \ || defined(BOOST_NO_CXX11_DECLTYPE)) \ + || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ || defined(BOOST_FUSION_DISABLE_VARIADIC_VECTOR) \ || (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)) # if defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) diff --git a/include/boost/fusion/container/vector/vector.hpp b/include/boost/fusion/container/vector/vector.hpp index a302bc93..62d2445e 100644 --- a/include/boost/fusion/container/vector/vector.hpp +++ b/include/boost/fusion/container/vector/vector.hpp @@ -24,24 +24,21 @@ /////////////////////////////////////////////////////////////////////////////// #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 @@ -54,56 +51,48 @@ namespace boost { namespace fusion namespace vector_detail { struct each_elem {}; - struct copy_or_move {}; - template struct from_sequence {}; - template - struct make_indices_from_seq - : detail::make_index_sequence< - fusion::result_of::size::type>::value + template < + typename This, typename T, typename T_, std::size_t Size, bool IsSeq + > + struct can_convert_impl : false_type {}; + + template + struct can_convert_impl : true_type {}; + + template + struct can_convert_impl + : integral_constant< + bool + , !is_convertible< + Sequence + , typename fusion::extension::value_at_impl:: + template apply< This, mpl::int_<0> >::type + >::value > {}; - template - struct pure : remove_cv::type> {}; - - template - struct can_convert : mpl::false_ {}; - - template - struct can_convert< - Sequence - , This - , typename enable_if>::type - > : mpl::equal_to< - fusion::result_of::size - , fusion::result_of::size + template + struct can_convert + : can_convert_impl< + This, T, T_, Size, traits::is_sequence::value > - { - }; + {}; - template - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - inline each_elem - dispatch(T const&...) BOOST_NOEXCEPT { return each_elem(); } + template + struct is_longer_sequence_impl : false_type {}; - template - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - inline copy_or_move - dispatch(This const&) BOOST_NOEXCEPT { return copy_or_move(); } - - template - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - inline from_sequence< - typename lazy_enable_if_c< - (!is_same::type>::value && - can_convert::type, This>::value) - , make_indices_from_seq - >::type - > - dispatch(Sequence&&) BOOST_NOEXCEPT - { return from_sequence::type>(); } + template + struct is_longer_sequence_impl + : integral_constant< + bool, (fusion::result_of::size::value >= Size) + > + {}; + template + struct is_longer_sequence + : is_longer_sequence_impl::value, Size> + {}; // forward_at_c allows to access Nth element even if ForwardSequence // since fusion::at_c requires RandomAccessSequence. @@ -168,22 +157,17 @@ namespace boost { namespace fusion return *this; } - template + template < + typename U + , typename = typename boost::disable_if< + is_base_of::type> + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - store(U&& rhs - , typename disable_if::type, store>, detail::enabler_>::type = detail::enabler) + store(U&& rhs) : elem(std::forward(rhs)) {} - template - BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED - typename disable_if::type, store>, store&>::type - operator=(U&& rhs) - { - elem = std::forward(rhs); - return *this; - } - BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED T & get() { return elem; } BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED @@ -211,21 +195,17 @@ namespace boost { namespace fusion vector_data() {} - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - vector_data(copy_or_move, vector_data const& rhs) - : store(static_cast const&>(rhs))... - {} - - BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED - vector_data(copy_or_move, vector_data&& rhs) - : store(std::forward >(rhs))... - {} - - template + template < + typename Sequence + , typename Sequence_ = typename remove_reference::type + , typename = typename boost::enable_if< + can_convert + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED explicit - vector_data(from_sequence >, Sequence&& rhs) - : store(forward_at_c(rhs))... + vector_data(each_elem, Sequence&& rhs) + : store(forward_at_c(std::forward(rhs)))... {} template @@ -235,6 +215,14 @@ namespace boost { namespace fusion : store(std::forward(var))... {} + template + BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED + void + assign_sequence(Sequence&& seq) + { + assign(std::forward(seq), detail::index_sequence()); + } + template BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED void @@ -299,15 +287,36 @@ namespace boost { namespace fusion vector() {} - // rvalue-references is required here in order to forward any arguments to - // base: vector(T const&...) doesn't work with trailing void_ and - // vector(U const&...) cannot forward any arguments to base. - template + template < + typename... U + , typename = typename boost::enable_if_c<( + sizeof...(U) >= 1 && + fusion::detail::and_...>::value && + !fusion::detail::and_< + is_base_of::type>... + >::value + )>::type + > // XXX: constexpr become error due to pull-request #79, booooo!! // In the (near) future release, should be fixed. /* BOOST_CONSTEXPR */ BOOST_FUSION_GPU_ENABLED - vector(U&&... u) - : base(vector_detail::dispatch(std::forward(u)...), std::forward(u)...) + explicit vector(U&&... u) + : base(vector_detail::each_elem(), std::forward(u)...) + {} + + template < + typename Sequence + , typename Sequence_ = typename remove_reference::type + , typename = typename boost::enable_if_c<( + !is_base_of::value && + vector_detail::is_longer_sequence< + Sequence_, sizeof...(T) + >::value + )>::type + > + BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED + vector(Sequence&& seq) + : base(vector_detail::each_elem(), std::forward(seq)) {} template @@ -315,10 +324,7 @@ namespace boost { namespace fusion vector& operator=(Sequence&& rhs) { - typedef typename - vector_detail::make_indices_from_seq::type - indices; - base::assign(std::forward(rhs), indices()); + base::assign_sequence(std::forward(rhs)); return *this; } }; diff --git a/include/boost/fusion/tuple/tuple.hpp b/include/boost/fusion/tuple/tuple.hpp index 606e1694..07014c6c 100644 --- a/include/boost/fusion/tuple/tuple.hpp +++ b/include/boost/fusion/tuple/tuple.hpp @@ -42,12 +42,22 @@ namespace boost { namespace fusion tuple() : base_type() {} - template + template < + typename ...U + , typename = typename boost::enable_if_c< + sizeof...(U) >= sizeof...(T) + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED tuple(tuple const& other) : base_type(other) {} - template + template < + typename ...U + , typename = typename boost::enable_if_c< + sizeof...(U) >= sizeof...(T) + >::type + > BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED tuple(tuple&& other) : base_type(std::move(other)) {} @@ -55,7 +65,7 @@ namespace boost { namespace fusion template < typename ...U , typename = typename boost::enable_if_c<( - fusion::detail::and_...>::value && + fusion::detail::and_...>::value && sizeof...(U) >= 1 )>::type > diff --git a/include/boost/fusion/tuple/tuple_fwd.hpp b/include/boost/fusion/tuple/tuple_fwd.hpp index f3e8deb0..b763acd5 100644 --- a/include/boost/fusion/tuple/tuple_fwd.hpp +++ b/include/boost/fusion/tuple/tuple_fwd.hpp @@ -12,7 +12,6 @@ #include #if !defined(BOOST_FUSION_HAS_VARIADIC_VECTOR) \ - || defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) \ || (defined(__WAVE__) && defined(BOOST_FUSION_CREATE_PREPROCESSED_FILES)) # if defined(BOOST_FUSION_HAS_VARIADIC_TUPLE) # undef BOOST_FUSION_HAS_VARIADIC_TUPLE diff --git a/test/Jamfile b/test/Jamfile index 7e5e4186..795ad317 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -123,6 +123,7 @@ project [ run sequence/array.cpp : : : : ] [ run sequence/tuple_comparison.cpp : : : : ] [ run sequence/tuple_construction.cpp : : : : ] + [ run sequence/tuple_conversion.cpp : : : : ] [ run sequence/tuple_copy.cpp : : : : ] [ run sequence/tuple_element.cpp : : : : ] [ run sequence/tuple_make.cpp : : : : ] @@ -136,18 +137,19 @@ project : : : - : sequence/tuple_traits/maybe_variadic_vector + : sequence/tuple_traits/maybe_variadic_tuple ] [ run sequence/tuple_traits.cpp : : : BOOST_FUSION_DISABLE_VARIADIC_VECTOR - : sequence/tuple_traits/no_variadic_vector + : sequence/tuple_traits/no_variadic_tuple ] [ run sequence/transform_view.cpp : : : : ] [ run sequence/vector_comparison.cpp : : : : ] [ run sequence/vector_construction.cpp : : : : ] + [ run sequence/vector_conversion.cpp : : : : ] [ run sequence/vector_copy.cpp : : : : ] [ run sequence/vector_iterator.cpp : : : : ] [ run sequence/vector_make.cpp : : : : ] @@ -158,6 +160,20 @@ project [ run sequence/vector_nest.cpp : : : : ] [ run sequence/vector_hash.cpp : : : : ] [ run sequence/vector_tie.cpp : : : : ] + [ + run sequence/vector_traits.cpp + : + : + : + : sequence/vector_traits/maybe_variadic_vector + ] + [ + run sequence/vector_traits.cpp + : + : + : BOOST_FUSION_DISABLE_VARIADIC_VECTOR + : sequence/vector_traits/no_variadic_vector + ] [ run sequence/vector_value_at.cpp : : : : ] [ run sequence/zip_view.cpp : : : : ] [ run sequence/zip_view2.cpp : : : : ] diff --git a/test/sequence/conversion.hpp b/test/sequence/conversion.hpp new file mode 100644 index 00000000..098f2be1 --- /dev/null +++ b/test/sequence/conversion.hpp @@ -0,0 +1,320 @@ +/*============================================================================= + Copyright (c) 2016 Lee Clagett + + Use modification and distribution are subject to the Boost Software + License, Version 1.0. (See accompanyintg file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt). +==============================================================================*/ + +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) +# include +#endif +#include +#include +#include +#include + +#include "fixture.hpp" + +template