commit 93a1fc3b87b7ad98d658b4d3e6ac564f6c64b12b Author: Mateusz Loskot Date: Tue Jul 2 13:28:20 2013 +0100 Initial version of std::array for Boost.Fusion Functional, though ADL issues have not been solved (see README). 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(); +}