diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/fusion/example | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/fusion/example')
39 files changed, 3545 insertions, 0 deletions
diff --git a/src/boost/libs/fusion/example/cookbook/do_the_bind.cpp b/src/boost/libs/fusion/example/cookbook/do_the_bind.cpp new file mode 100644 index 00000000..ac5baee4 --- /dev/null +++ b/src/boost/libs/fusion/example/cookbook/do_the_bind.cpp @@ -0,0 +1,268 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are 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). + + Problem: + + How to "do the Bind?" + + This recipe shows how to implement a function binder, similar to + Boost.Bind based on the Functional module of Fusion. + + It works as follows: + + 'bind' is a global, stateless function object. It is implemented in + fused form (fused_binder) and transformed into a variadic function + object. When called, 'bind' returns another function object, which + holds the arguments of the call to 'bind'. It is, again, implemented + in fused form (fused_bound_function) and transformed into unfused + form. +==============================================================================*/ + + +#include <boost/fusion/functional/invocation/invoke.hpp> +#include <boost/fusion/functional/adapter/unfused.hpp> +#include <boost/fusion/support/deduce_sequence.hpp> + +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/fusion/sequence/intrinsic/front.hpp> +#include <boost/fusion/sequence/intrinsic/size.hpp> +#include <boost/fusion/algorithm/transformation/transform.hpp> +#include <boost/fusion/algorithm/transformation/pop_front.hpp> +#include <boost/fusion/algorithm/iteration/fold.hpp> +#include <boost/fusion/view/filter_view.hpp> + +#include <boost/functional/forward_adapter.hpp> +#include <boost/functional/lightweight_forward_adapter.hpp> + +#include <boost/type_traits/remove_reference.hpp> + +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/max.hpp> +#include <boost/mpl/next.hpp> + +#include <boost/ref.hpp> +#include <iostream> +#include <typeinfo> + +namespace impl +{ + namespace fusion = boost::fusion; + namespace traits = boost::fusion::traits; + namespace result_of = boost::fusion::result_of; + namespace mpl = boost::mpl; + using mpl::placeholders::_; + + // Placeholders (we inherit from mpl::int_, so we can use placeholders + // as indices for fusion::at, later) + template <int I> struct placeholder : mpl::int_<I> { }; + + // A traits class to find out whether T is a placeholeder + template <typename T> struct is_placeholder : mpl::false_ { }; + template <int I> struct is_placeholder< placeholder<I> > : mpl::true_ { }; + template <int I> struct is_placeholder< placeholder<I> & > : mpl::true_ { }; + template <int I> struct is_placeholder< placeholder<I> const > : mpl::true_ { }; + template <int I> struct is_placeholder< placeholder<I> const & > : mpl::true_ { }; + + // This class template provides a Polymorphic Function Object to be used + // with fusion::transform. It is applied to the sequence of arguments that + // describes the binding and holds a reference to the sequence of arguments + // from the final call. + template<class FinalArgs> struct argument_transform + { + FinalArgs const & ref_final_args; + public: + + explicit argument_transform(FinalArgs const & final_args) + : ref_final_args(final_args) + { } + + // A placeholder? Replace it with an argument from the final call... + template <int Index> + inline typename result_of::at_c<FinalArgs const, Index>::type + operator()(placeholder<Index> const &) const + { + return fusion::at_c<Index>(this->ref_final_args); + } + // ...just return the bound argument, otherwise. + template <typename T> inline T & operator()(T & bound) const + { + return bound; + } + + template <typename Signature> + struct result; + + template <class Self, typename T> + struct result< Self (T) > + : mpl::eval_if< is_placeholder<T>, + result_of::at<FinalArgs,typename boost::remove_reference<T>::type>, + mpl::identity<T> + > + { }; + }; + + // Fused implementation of the bound function, the function object + // returned by bind + template <class BindArgs> class fused_bound_function + { + // Transform arguments to be held by value + typedef typename traits::deduce_sequence<BindArgs>::type bound_args; + + bound_args fsq_bind_args; + public: + + fused_bound_function(BindArgs const & bind_args) + : fsq_bind_args(bind_args) + { } + + template <typename Signature> + struct result; + + template <class FinalArgs> + struct result_impl + : result_of::invoke< typename result_of::front<bound_args>::type, + typename result_of::transform< + typename result_of::pop_front<bound_args>::type, + argument_transform<FinalArgs> const + >::type + > + { }; + + template <class Self, class FinalArgs> + struct result< Self (FinalArgs) > + : result_impl< typename boost::remove_reference<FinalArgs>::type > + { }; + + template <class FinalArgs> + inline typename result_impl<FinalArgs>::type + operator()(FinalArgs const & final_args) const + { + return fusion::invoke( fusion::front(this->fsq_bind_args), + fusion::transform( fusion::pop_front(this->fsq_bind_args), + argument_transform<FinalArgs>(final_args) ) ); + } + // Could add a non-const variant - omitted for readability + + }; + + // Find the number of placeholders in use + struct n_placeholders + { + struct fold_op + { + template <typename Sig> struct result; + template <class S, class A, class B> struct result< S(A &,B &) > + : mpl::max<A,B> { }; + }; + struct filter_pred + { + template <class X> struct apply : is_placeholder<X> { }; + }; + + template <typename Seq> + struct apply + : mpl::next< typename result_of::fold< + fusion::filter_view<Seq,filter_pred>, mpl::int_<-1>, fold_op + >::type>::type + { }; + }; + + // Fused implementation of the 'bind' function + struct fused_binder + { + template <class Signature> + struct result; + + template <class BindArgs, + int Placeholders = n_placeholders::apply<BindArgs>::value> + struct result_impl + { + typedef boost::forward_adapter<fusion::unfused< + fused_bound_function<BindArgs>,!Placeholders>,Placeholders> type; + }; + + template <class Self, class BindArgs> + struct result< Self (BindArgs) > + : result_impl< typename boost::remove_reference<BindArgs>::type > + { }; + + template <class BindArgs> + inline typename result_impl< BindArgs >::type + operator()(BindArgs & bind_args) const + { + return typename result< void(BindArgs) >::type( + fusion::unfused< fused_bound_function<BindArgs>, + ! n_placeholders::apply<BindArgs>::value >(bind_args) ); + } + }; + + // The binder's unfused type. We use lightweght_forward_adapter to make + // that thing more similar to Boost.Bind. Because of that we have to use + // Boost.Ref (below in the sample code) + typedef boost::lightweight_forward_adapter< fusion::unfused<fused_binder> > binder; +} + +// Placeholder globals +impl::placeholder<0> const _1_ = impl::placeholder<0>(); +impl::placeholder<1> const _2_ = impl::placeholder<1>(); +impl::placeholder<2> const _3_ = impl::placeholder<2>(); +impl::placeholder<3> const _4_ = impl::placeholder<3>(); + +// The bind function is a global, too +impl::binder const bind = impl::binder(); + + +// OK, let's try it out: + +struct func +{ + typedef int result_type; + + inline int operator()() const + { + std::cout << "operator()" << std::endl; + return 0; + } + + template <typename A> + inline int operator()(A const & a) const + { + std::cout << "operator()(A const & a)" << std::endl; + std::cout << " a = " << a << " A = " << typeid(A).name() << std::endl; + return 1; + } + + template <typename A, typename B> + inline int operator()(A const & a, B & b) const + { + std::cout << "operator()(A const & a, B & b)" << std::endl; + std::cout << " a = " << a << " A = " << typeid(A).name() << std::endl; + std::cout << " b = " << b << " B = " << typeid(B).name() << std::endl; + return 2; + } +}; + +int main() +{ + func f; + int value = 42; + using boost::ref; + + int errors = 0; + + errors += !( bind(f)() == 0); + errors += !( bind(f,"Hi")() == 1); + errors += !( bind(f,_1_)("there.") == 1); + errors += !( bind(f,"The answer is",_1_)(12) == 2); + errors += !( bind(f,_1_,ref(value))("Really?") == 2); + errors += !( bind(f,_1_,_2_)("Dunno. If there is an answer, it's",value) == 2); + + return !! errors; +} + diff --git a/src/boost/libs/fusion/example/cookbook/fill_em_up.cpp b/src/boost/libs/fusion/example/cookbook/fill_em_up.cpp new file mode 100644 index 00000000..9b37aec8 --- /dev/null +++ b/src/boost/libs/fusion/example/cookbook/fill_em_up.cpp @@ -0,0 +1,105 @@ +/*============================================================================= + Copyright (c) 2011 Joel de Guzman + + 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) + + Problem: + + So... you have an input sequence I and a target vector R. You want to + copy I into R. But, I may have less elements than the result vector R. + For those elements not in R, you want them to be default constructed. + + Here's a case: + + I: list<double, std::string> + R: vector<double, std::string, int, short> + + You want the elements at the right of I not in R (i.e. int, short) + default constructed. Those at the left, found in both I and R, you want + to simply copy from I. + + Of course you want to be able to handle any type of I and R. + +==============================================================================*/ + +// We'll use these containers as examples +#include <boost/fusion/container/list.hpp> +#include <boost/fusion/container/vector.hpp> + +// For doing I/O +#include <boost/fusion/sequence/io.hpp> + +// We'll use join and advance for processing +#include <boost/fusion/algorithm/transformation/join.hpp> +#include <boost/fusion/iterator/advance.hpp> + +// The fusion <--> MPL link header +#include <boost/fusion/mpl.hpp> + +// Same-o same-o +#include <iostream> +#include <string> + +int +main() +{ + using namespace boost::fusion; + using namespace boost; + + // Let's specify our own tuple delimeters for nicer printing + std::cout << tuple_open('['); + std::cout << tuple_close(']'); + std::cout << tuple_delimiter(", "); + + // Here's your input sequence + typedef list<double, std::string> I; + I i(123.456, "Hello"); + + // Here's your output sequence. For now, it is just a typedef + typedef vector<double, std::string, int, short> R; + + // Let's get the sizes of the sequences. Yeah, you already know that. + // But with templates, you are simply given, say, R and I, corresponding + // to the types of the sequences. You'll have to deal with it generically. + static int const r_size = result_of::size<R>::value; + static int const i_size = result_of::size<I>::value; + + // Make sure that I has no more elements than R + // Be nice and catch obvious errors earlier rather than later. + // Without this assert, the mistake will still be caught by Fusion, + // but the error will point to somewhere really obscure. + BOOST_STATIC_ASSERT(i_size <= r_size); + + // Let's get the begin and end iterator types of the output sequence + // There's no actual vector yet. We just want to know the types. + typedef result_of::begin<R>::type r_begin; + typedef result_of::end<R>::type r_end; + + // Let's skip i_size elements from r_begin. Again, we just want to know the type. + typedef result_of::advance_c<r_begin, i_size>::type r_advance; + + // Now, make MPL iterators from r_advance and r_end. Ditto, just types. + typedef mpl::fusion_iterator<r_advance> mpl_r_advance; + typedef mpl::fusion_iterator<r_end> mpl_r_end; + + // Make an mpl::iterator_range from the MPL iterators we just created + // You guessed it! --just a type. + typedef mpl::iterator_range<mpl_r_advance, mpl_r_end> tail; + + // Use join to join the input sequence and our mpl::iterator_range + // Our mpl::iterator_range is 'tail'. Here, we'll actually instantiate + // 'tail'. Notice that this is a flyweight object, typically just 1 byte + // in size -- it doesn't really hold any data, but is a fully conforming + // sequence nonetheless. When asked to return its elements, 'tail' returns + // each element default constructed. Breeds like a rabbit! + + // Construct R from the joined sequences: + R r(join(i, tail())); + + // Then finally, print the result: + std::cout << r << std::endl; + + return 0; +} + diff --git a/src/boost/libs/fusion/example/extension/Jamfile b/src/boost/libs/fusion/example/extension/Jamfile new file mode 100644 index 00000000..aabe8302 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/Jamfile @@ -0,0 +1,20 @@ +#============================================================================== +# Copyright (c) 2003-2006 Joel de Guzman +# Copyright (c) 2006 Dan Marsden +# +# 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 ; + +{ + test-suite example : + + [ run test_example.cpp : : : : ] + [ run triple.cpp : : : : ] + ; +} + diff --git a/src/boost/libs/fusion/example/extension/detail/advance_impl.hpp b/src/boost/libs/fusion/example/extension/detail/advance_impl.hpp new file mode 100644 index 00000000..0d778123 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/advance_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_ADVANCE_IMPL_20060222_2150) +#define BOOST_FUSION_ADVANCE_IMPL_20060222_2150 + +namespace example +{ + struct example_struct_iterator_tag; + + template<typename Struct, int Pos> + struct example_struct_iterator; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct advance_impl; + + template<> + struct advance_impl<example::example_struct_iterator_tag> + { + template<typename Iterator, typename N> + struct apply + { + typedef typename Iterator::struct_type struct_type; + typedef typename Iterator::index index; + typedef example::example_struct_iterator< + struct_type, index::value + N::value> type; + + static type + call(Iterator const& it) + { + return type(it.struct_); + } + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/at_impl.hpp b/src/boost/libs/fusion/example/extension/detail/at_impl.hpp new file mode 100644 index 00000000..60558930 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/at_impl.hpp @@ -0,0 +1,67 @@ +/*============================================================================= + 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_AT_IMPL_20060223_2017) +#define BOOST_FUSION_AT_IMPL_20060223_2017 + +#include <string> +#include <boost/mpl/if.hpp> +#include <boost/mpl/int.hpp> +#include <boost/type_traits/is_const.hpp> + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct at_impl; + + template<> + struct at_impl<example::example_sequence_tag> + { + template<typename Sequence, typename Key> + struct apply; + + template<typename Sequence> + struct apply<Sequence, mpl::int_<0> > + { + typedef typename mpl::if_< + is_const<Sequence>, + std::string const&, + std::string&>::type type; + + static type + call(Sequence& seq) + { + return seq.name; + }; + }; + + template<typename Sequence> + struct apply<Sequence, mpl::int_<1> > + { + typedef typename mpl::if_< + is_const<Sequence>, + int const&, + int&>::type type; + + static type + call(Sequence& seq) + { + return seq.age; + }; + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/at_key_impl.hpp b/src/boost/libs/fusion/example/extension/detail/at_key_impl.hpp new file mode 100644 index 00000000..e925c62a --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/at_key_impl.hpp @@ -0,0 +1,72 @@ +/*============================================================================= + 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_AT_KEY_IMPL_20060223_2017) +#define BOOST_FUSION_AT_KEY_IMPL_20060223_2017 + +#include <string> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_const.hpp> + +namespace fields +{ + struct name; + struct age; +} + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct at_key_impl; + + template<> + struct at_key_impl<example::example_sequence_tag> + { + template<typename Sequence, typename Key> + struct apply; + + template<typename Sequence> + struct apply<Sequence, fields::name> + { + typedef typename mpl::if_< + is_const<Sequence>, + std::string const&, + std::string&>::type type; + + static type + call(Sequence& seq) + { + return seq.name; + }; + }; + + template<typename Sequence> + struct apply<Sequence, fields::age> + { + typedef typename mpl::if_< + is_const<Sequence>, + int const&, + int&>::type type; + + static type + call(Sequence& seq) + { + return seq.age; + }; + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/begin_impl.hpp b/src/boost/libs/fusion/example/extension/detail/begin_impl.hpp new file mode 100644 index 00000000..a4296c59 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/begin_impl.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + 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_BEGIN_IMPL_20060222_2042) +#define BOOST_FUSION_BEGIN_IMPL_20060222_2042 + +#include "../example_struct_iterator.hpp" + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct begin_impl; + + template<> + struct begin_impl<example::example_sequence_tag> + { + template<typename Sequence> + struct apply + { + typedef example::example_struct_iterator<Sequence, 0> type; + + static type + call(Sequence& seq) + { + return type(seq); + } + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/category_of_impl.hpp b/src/boost/libs/fusion/example/extension/detail/category_of_impl.hpp new file mode 100644 index 00000000..b0bc7d90 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/category_of_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + 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_CATEGORY_OF_IMPL_20060223_2037) +#define BOOST_FUSION_CATEGORY_OF_IMPL_20060223_2037 + +#include <boost/fusion/support/category_of.hpp> + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<> + struct category_of_impl<example::example_sequence_tag> + { + template<typename Sequence> + struct apply + { + struct type : random_access_traversal_tag, associative_tag {}; + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/deref_data_impl.hpp b/src/boost/libs/fusion/example/extension/detail/deref_data_impl.hpp new file mode 100644 index 00000000..c9907d5c --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/deref_data_impl.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2009 Christopher Schmidt + + 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_EXAMPLE_EXTENSION_DETAIL_DEREF_DATA_IMPL_HPP +#define BOOST_FUSION_EXAMPLE_EXTENSION_DETAIL_DEREF_DATA_IMPL_HPP + +namespace example +{ + struct example_struct_iterator_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct deref_data_impl; + + template<> + struct deref_data_impl<example::example_struct_iterator_tag> + : deref_impl<example::example_struct_iterator_tag> + {}; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/deref_impl.hpp b/src/boost/libs/fusion/example/extension/detail/deref_impl.hpp new file mode 100644 index 00000000..7e515e9d --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/deref_impl.hpp @@ -0,0 +1,67 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_DEREF_IMPL_20060222_1952) +#define BOOST_FUSION_DEREF_IMPL_20060222_1952 + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/mpl/if.hpp> + +#include <string> + +namespace example +{ + struct example_struct_iterator_tag; + + template<typename Struct, int Pos> + struct example_struct_iterator; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct deref_impl; + + template<> + struct deref_impl<example::example_struct_iterator_tag> + { + template<typename Iterator> + struct apply; + + template<typename Struct> + struct apply<example::example_struct_iterator<Struct, 0> > + { + typedef typename mpl::if_< + is_const<Struct>, std::string const&, std::string&>::type type; + + static type + call(example::example_struct_iterator<Struct, 0> const& it) + { + return it.struct_.name; + } + }; + + template<typename Struct> + struct apply<example::example_struct_iterator<Struct, 1> > + { + typedef typename mpl::if_< + is_const<Struct>, int const&, int&>::type type; + + static type + call(example::example_struct_iterator<Struct, 1> const& it) + { + return it.struct_.age; + } + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/distance_impl.hpp b/src/boost/libs/fusion/example/extension/detail/distance_impl.hpp new file mode 100644 index 00000000..b138cc4a --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/distance_impl.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_DISTANCE_IMPL_20060223_0814) +#define BOOST_FUSION_DISTANCE_IMPL_20060223_0814 + +#include <boost/mpl/minus.hpp> + +namespace example +{ + struct example_struct_iterator_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct distance_impl; + + template<> + struct distance_impl<example::example_struct_iterator_tag> + { + template<typename First, typename Last> + struct apply + : mpl::minus<typename Last::index, typename First::index> + { + typedef apply<First, Last> self; + + static typename self::type + call(First const& first, Last const& last) + { + return typename self::type(); + } + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/end_impl.hpp b/src/boost/libs/fusion/example/extension/detail/end_impl.hpp new file mode 100644 index 00000000..749bb33a --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/end_impl.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + 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_END_IMPL_20060222_2042) +#define BOOST_FUSION_END_IMPL_20060222_2042 + +#include "../example_struct_iterator.hpp" + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct end_impl; + + template<> + struct end_impl<example::example_sequence_tag> + { + template<typename Sequence> + struct apply + { + typedef example::example_struct_iterator<Sequence, 2> type; + + static type + call(Sequence& seq) + { + return type(seq); + } + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/equal_to_impl.hpp b/src/boost/libs/fusion/example/extension/detail/equal_to_impl.hpp new file mode 100644 index 00000000..8ab27649 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/equal_to_impl.hpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_EQUAL_TO_IMPL_20060223_1941) +#define BOOST_FUSION_EQUAL_TO_IMPL_20060223_1941 + +#include <boost/mpl/equal_to.hpp> + +namespace example +{ + struct example_struct_iterator_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct equal_to_impl; + + template<> + struct equal_to_impl<example::example_struct_iterator_tag> + { + template<typename It1, typename It2> + struct apply + : mpl::equal_to< + typename It1::index, + typename It2::index> + {}; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/has_key_impl.hpp b/src/boost/libs/fusion/example/extension/detail/has_key_impl.hpp new file mode 100644 index 00000000..596827ce --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/has_key_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_HAS_KEY_IMPL_20060223_2156) +#define BOOST_FUSION_HAS_KEY_IMPL_20060223_2156 + +#include <boost/type_traits/is_same.hpp> +#include <boost/mpl/or.hpp> + +namespace fields +{ + struct name; + struct age; +} + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct has_key_impl; + + template<> + struct has_key_impl<example::example_sequence_tag> + { + template<typename Sequence, typename Key> + struct apply + : mpl::or_< + is_same<Key, fields::name>, + is_same<Key, fields::age> > + {}; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/is_sequence_impl.hpp b/src/boost/libs/fusion/example/extension/detail/is_sequence_impl.hpp new file mode 100644 index 00000000..e373342a --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/is_sequence_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + 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_IS_SEQUENCE_IMPL_20060228_1946) +#define BOOST_FUSION_IS_SEQUENCE_IMPL_20060228_1946 + +#include <boost/mpl/bool.hpp> + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion +{ + namespace extension + { + template<typename Tag> + struct is_sequence_impl; + + template<> + struct is_sequence_impl<example::example_sequence_tag> + { + template<typename T> + struct apply : mpl::true_ {}; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/is_view_impl.hpp b/src/boost/libs/fusion/example/extension/detail/is_view_impl.hpp new file mode 100644 index 00000000..b2344bf2 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/is_view_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_IS_VIEW_IMPL_200604227_2150) +#define BOOST_FUSION_IS_VIEW_IMPL_200604227_2150 + +#include <boost/mpl/bool.hpp> + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion +{ + namespace extension + { + template<typename Tag> + struct is_view_impl; + + template<> + struct is_view_impl<example::example_sequence_tag> + : boost::mpl::false_ + {}; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/key_of_impl.hpp b/src/boost/libs/fusion/example/extension/detail/key_of_impl.hpp new file mode 100644 index 00000000..6a7a836d --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/key_of_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2009 Christopher Schmidt + + 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_EXAMPLE_EXTENSION_DETAIL_KEY_OF_IMPL_HPP +#define BOOST_FUSION_EXAMPLE_EXTENSION_DETAIL_KEY_OF_IMPL_HPP + +#include <boost/mpl/if.hpp> + +namespace fields +{ + struct name; + struct age; +} + +namespace example +{ + struct example_struct_iterator_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct key_of_impl; + + template<> + struct key_of_impl<example::example_struct_iterator_tag> + { + template<typename It> + struct apply + : mpl::if_c<!It::index::value, fields::name, fields::age> + {}; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/next_impl.hpp b/src/boost/libs/fusion/example/extension/detail/next_impl.hpp new file mode 100644 index 00000000..8fbaa8b1 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/next_impl.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_NEXT_IMPL_20060222_1859) +#define BOOST_FUSION_NEXT_IMPL_20060222_1859 + +namespace example +{ + struct example_struct_iterator_tag; + + template<typename Struct, int Pos> + struct example_struct_iterator; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct next_impl; + + template<> + struct next_impl<example::example_struct_iterator_tag> + { + template<typename Iterator> + struct apply + { + typedef typename Iterator::struct_type struct_type; + typedef typename Iterator::index index; + typedef example::example_struct_iterator<struct_type, index::value + 1> type; + + static type + call(Iterator const& i) + { + return type(i.struct_); + } + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/prior_impl.hpp b/src/boost/libs/fusion/example/extension/detail/prior_impl.hpp new file mode 100644 index 00000000..415692ce --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/prior_impl.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_PRIOR_IMPL_20060222_1944) +#define BOOST_FUSION_PRIOR_IMPL_20060222_1944 + +namespace example +{ + struct example_struct_iterator_tag; + + template<typename Struct, int Pos> + struct example_struct_iterator; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct prior_impl; + + template<> + struct prior_impl<example::example_struct_iterator_tag> + { + template<typename Iterator> + struct apply + { + typedef typename Iterator::struct_type struct_type; + typedef typename Iterator::index index; + typedef example::example_struct_iterator<struct_type, index::value - 1> type; + + static type + call(Iterator const& i) + { + return type(i.struct_); + } + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/size_impl.hpp b/src/boost/libs/fusion/example/extension/detail/size_impl.hpp new file mode 100644 index 00000000..4dc6ec93 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/size_impl.hpp @@ -0,0 +1,36 @@ +/*============================================================================= + 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_SIZE_IMPL_20060223_2033) +#define BOOST_FUSION_SIZE_IMPL_20060223_2033 + +#include <boost/mpl/int.hpp> + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct size_impl; + + template<> + struct size_impl<example::example_sequence_tag> + { + template<typename Sequence> + struct apply + : mpl::int_<2> + {}; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/value_at_impl.hpp b/src/boost/libs/fusion/example/extension/detail/value_at_impl.hpp new file mode 100644 index 00000000..6a1d63ef --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/value_at_impl.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + 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_VALUE_AT_IMPL_20060223_2025) +#define BOOST_FUSION_VALUE_AT_IMPL_20060223_2025 + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct value_at_impl; + + template<> + struct value_at_impl<example::example_sequence_tag> + { + template<typename Sequence, typename N> + struct apply; + + template<typename Sequence> + struct apply<Sequence, mpl::int_<0> > + { + typedef std::string type; + }; + + template<typename Sequence> + struct apply<Sequence, mpl::int_<1> > + { + typedef int type; + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/value_at_key_impl.hpp b/src/boost/libs/fusion/example/extension/detail/value_at_key_impl.hpp new file mode 100644 index 00000000..cabc59aa --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/value_at_key_impl.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + 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_VALUE_AT_KEY_IMPL_20060223_2025) +#define BOOST_FUSION_VALUE_AT_KEY_IMPL_20060223_2025 + +namespace fields +{ + struct name; + struct age; +} + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct value_at_key_impl; + + template<> + struct value_at_key_impl<example::example_sequence_tag> + { + template<typename Sequence, typename N> + struct apply; + + template<typename Sequence> + struct apply<Sequence, fields::name> + { + typedef std::string type; + }; + + template<typename Sequence> + struct apply<Sequence, fields::age> + { + typedef int type; + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/value_of_data_impl.hpp b/src/boost/libs/fusion/example/extension/detail/value_of_data_impl.hpp new file mode 100644 index 00000000..94cdcc30 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/value_of_data_impl.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2009 Christopher Schmidt + + 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_EXAMPLE_EXTENSION_DETAIL_VALUE_OF_DATA_IMPL_HPP +#define BOOST_FUSION_EXAMPLE_EXTENSION_DETAIL_VALUE_OF_DATA_IMPL_HPP + +namespace example +{ + struct example_struct_iterator_tag; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct value_of_data_impl; + + template<> + struct value_of_data_impl<example::example_struct_iterator_tag> + : value_of_impl<example::example_struct_iterator_tag> + {}; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/detail/value_of_impl.hpp b/src/boost/libs/fusion/example/extension/detail/value_of_impl.hpp new file mode 100644 index 00000000..6fc7e161 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/detail/value_of_impl.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_VALUE_OF_IMPL_20060223_1905) +#define BOOST_FUSION_VALUE_OF_IMPL_20060223_1905 + +#include <string> + +namespace example +{ + struct example_struct_iterator_tag; + + template<typename Struct, int Pos> + struct example_struct_iterator; +} + +namespace boost { namespace fusion { + + namespace extension + { + template<typename Tag> + struct value_of_impl; + + template<> + struct value_of_impl<example::example_struct_iterator_tag> + { + template<typename Iterator> + struct apply; + + template<typename Struct> + struct apply<example::example_struct_iterator<Struct, 0> > + { + typedef std::string type; + }; + + template<typename Struct> + struct apply<example::example_struct_iterator<Struct, 1> > + { + typedef int type; + }; + }; + } +}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/example_struct.hpp b/src/boost/libs/fusion/example/extension/example_struct.hpp new file mode 100644 index 00000000..cbb058f5 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/example_struct.hpp @@ -0,0 +1,25 @@ +/*============================================================================= + 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_EXAMPLE_STRUCT) +#define BOOST_FUSION_EXAMPLE_STRUCT + +#include "./tag_of.hpp" +#include "./example_struct_iterator.hpp" +#include "./detail/begin_impl.hpp" +#include "./detail/end_impl.hpp" +#include "./detail/at_impl.hpp" +#include "./detail/value_at_impl.hpp" +#include "./detail/size_impl.hpp" +#include "./detail/category_of_impl.hpp" +#include "./detail/at_key_impl.hpp" +#include "./detail/value_at_key_impl.hpp" +#include "./detail/has_key_impl.hpp" +#include "./detail/is_sequence_impl.hpp" +#include "./detail/is_view_impl.hpp" + +#endif diff --git a/src/boost/libs/fusion/example/extension/example_struct_iterator.hpp b/src/boost/libs/fusion/example/extension/example_struct_iterator.hpp new file mode 100644 index 00000000..fa04f085 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/example_struct_iterator.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + 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_EXAMPLE_STRUCT_ITERATOR) +#define BOOST_FUSION_EXAMPLE_STRUCT_ITERATOR + +#include <boost/fusion/support/iterator_base.hpp> +#include <boost/fusion/support/category_of.hpp> +#include <boost/fusion/support/tag_of_fwd.hpp> +#include <boost/mpl/int.hpp> +#include <boost/type_traits/add_const.hpp> +#include <boost/static_assert.hpp> + +#include "./detail/next_impl.hpp" +#include "./detail/prior_impl.hpp" +#include "./detail/deref_impl.hpp" +#include "./detail/advance_impl.hpp" +#include "./detail/distance_impl.hpp" +#include "./detail/value_of_impl.hpp" +#include "./detail/equal_to_impl.hpp" +#include "./detail/key_of_impl.hpp" +#include "./detail/value_of_data_impl.hpp" +#include "./detail/deref_data_impl.hpp" + +namespace example +{ + struct example_struct_iterator_tag; + + template<typename Struct, int Pos> + struct example_struct_iterator; +} + +namespace boost { namespace fusion { + + namespace traits + { + template<typename Struct, int Pos> + struct tag_of<example::example_struct_iterator<Struct, Pos> > + { + typedef example::example_struct_iterator_tag type; + }; + } +}} + +namespace example { + template<typename Struct, int Pos> + struct example_struct_iterator + : boost::fusion::iterator_base<example_struct_iterator<Struct, Pos> > + { + BOOST_STATIC_ASSERT(Pos >=0 && Pos < 3); + typedef Struct struct_type; + typedef boost::mpl::int_<Pos> index; + + struct category + : boost::fusion::random_access_traversal_tag + , boost::fusion::associative_tag + {}; + + example_struct_iterator(Struct& str) + : struct_(str) {} + + Struct& struct_; + }; +} + +#endif diff --git a/src/boost/libs/fusion/example/extension/example_struct_type.hpp b/src/boost/libs/fusion/example/extension/example_struct_type.hpp new file mode 100644 index 00000000..e1d8e175 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/example_struct_type.hpp @@ -0,0 +1,27 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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_EXAMPLE_STRUCT_TYPE) +#define BOOST_FUSION_EXAMPLE_STRUCT_TYPE + +#include <string> + +namespace example +{ + struct example_struct + { + std::string name; + int age; + example_struct( + const std::string& n, + int a) + : name(n), age(a) + {} + }; +} + +#endif diff --git a/src/boost/libs/fusion/example/extension/tag_of.hpp b/src/boost/libs/fusion/example/extension/tag_of.hpp new file mode 100644 index 00000000..083b730c --- /dev/null +++ b/src/boost/libs/fusion/example/extension/tag_of.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + 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_TAG_OF_20060222_2052) +#define BOOST_FUSION_TAG_OF_20060222_2052 + +#include <boost/fusion/support/tag_of_fwd.hpp> +#include "./example_struct_type.hpp" + +namespace example +{ + struct example_sequence_tag; +} + +namespace boost { namespace fusion { + +namespace traits { + + template<> + struct tag_of<example::example_struct> + { + typedef example::example_sequence_tag type; + }; +}}} + +#endif diff --git a/src/boost/libs/fusion/example/extension/test_example.cpp b/src/boost/libs/fusion/example/extension/test_example.cpp new file mode 100644 index 00000000..581e2300 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/test_example.cpp @@ -0,0 +1,65 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 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) +==============================================================================*/ +#include "./example_struct.hpp" +#include "./example_struct_type.hpp" +#include <boost/detail/lightweight_test.hpp> + +#include <boost/fusion/sequence/intrinsic.hpp> +#include <boost/fusion/support/is_sequence.hpp> +#include <boost/fusion/support/category_of.hpp> +#include <boost/fusion/iterator.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/mpl/assert.hpp> + +int main() +{ + example::example_struct bert("bert", 99); + using namespace boost::fusion; + + BOOST_MPL_ASSERT((traits::is_associative<example::example_struct>)); + BOOST_MPL_ASSERT((traits::is_random_access<example::example_struct>)); + BOOST_MPL_ASSERT((traits::is_sequence<example::example_struct>)); + + BOOST_TEST(deref(begin(bert)) == "bert"); + BOOST_TEST(*next(begin(bert)) == 99); + BOOST_TEST(*prior(end(bert)) == 99); + BOOST_TEST(*advance_c<1>(begin(bert)) == 99); + BOOST_TEST(*advance_c<-1>(end(bert)) == 99); + BOOST_TEST(distance(begin(bert), end(bert)) == 2); + + typedef result_of::begin<example::example_struct>::type first; + typedef result_of::next<first>::type second; + BOOST_MPL_ASSERT((boost::is_same<result_of::value_of<first>::type, std::string>)); + BOOST_MPL_ASSERT((boost::is_same<result_of::value_of<second>::type, int>)); + + BOOST_TEST(begin(bert) != end(bert)); + BOOST_TEST(advance_c<2>(begin(bert)) == end(const_cast<const example::example_struct&>(bert))); + + BOOST_TEST(at_c<0>(bert) == "bert"); + BOOST_TEST(at_c<1>(bert) == 99); + + BOOST_TEST(at_key<fields::name>(bert) == "bert"); + BOOST_TEST(at_key<fields::age>(bert) == 99); + + BOOST_TEST(has_key<fields::name>(bert)); + BOOST_TEST(has_key<fields::age>(bert)); + BOOST_TEST(!has_key<int>(bert)); + + BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_c<example::example_struct, 0>::type, std::string>)); + BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_c<example::example_struct, 1>::type, int>)); + + BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_key<example::example_struct, fields::name>::type, std::string>)); + BOOST_MPL_ASSERT((boost::is_same<result_of::value_at_key<example::example_struct, fields::age>::type, int>)); + + BOOST_TEST(deref_data(begin(bert)) == "bert"); + BOOST_TEST(deref_data(next(begin(bert))) == 99); + + BOOST_TEST(size(bert) == 2); + + return boost::report_errors(); +} diff --git a/src/boost/libs/fusion/example/extension/triple.cpp b/src/boost/libs/fusion/example/extension/triple.cpp new file mode 100644 index 00000000..ac8f18e0 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/triple.cpp @@ -0,0 +1,377 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2011 Nathan Ridge + Copyright (c) 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) +==============================================================================*/ + +/*============================================================================= + An implementation of a std::pair like triple<T0, T1, T2> + We use fusion::sequence_facade and fusion::iterator_facade + to make our triple a fully conforming Boost.Fusion random + traversal sequence. +==============================================================================*/ + +#include <boost/detail/lightweight_test.hpp> + +#include <boost/fusion/sequence/sequence_facade.hpp> +#include <boost/fusion/iterator/iterator_facade.hpp> +#include <boost/fusion/sequence/intrinsic.hpp> +#include <boost/fusion/iterator.hpp> +#include <boost/fusion/support/category_of.hpp> +#include <boost/fusion/algorithm/iteration/fold.hpp> + +#include <boost/mpl/int.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/minus.hpp> +#include <boost/mpl/assert.hpp> + +#include <boost/type_traits/is_const.hpp> +#include <boost/type_traits/is_same.hpp> + +#include <string> + +namespace mpl = boost::mpl; +namespace fusion = boost::fusion; + +namespace demo +{ + template<typename Seq, int N> + struct triple_iterator + : fusion::iterator_facade<triple_iterator<Seq, N>, + fusion::random_access_traversal_tag> + { + typedef mpl::int_<N> index; + typedef Seq sequence_type; + + triple_iterator(Seq& seq) + : seq_(seq) {} + + Seq& seq_; + + template<typename T> + struct value_of; + + template<typename Sq> + struct value_of<triple_iterator<Sq, 0> > + : mpl::identity<typename Sq::t0_type> + {}; + + template<typename Sq> + struct value_of<triple_iterator<Sq, 1> > + : mpl::identity<typename Sq::t1_type> + {}; + + template<typename Sq> + struct value_of<triple_iterator<Sq, 2> > + : mpl::identity<typename Sq::t2_type> + {}; + + template<typename T> + struct deref; + + template <typename Sq> + struct deref<triple_iterator<Sq, 0> > + { + typedef typename Sq::t0_type& type; + + static type + call(triple_iterator<Sq, 0> const& iter) + { + return iter.seq_.t0; + } + }; + + template <typename Sq> + struct deref<triple_iterator<Sq, 0> const> + { + typedef typename Sq::t0_type const& type; + + static type + call(triple_iterator<Sq, 0> const& iter) + { + return iter.seq_.t0; + } + }; + + template <typename Sq> + struct deref<triple_iterator<Sq, 1> > + { + typedef typename Sq::t1_type& type; + + static type + call(triple_iterator<Sq, 1> const& iter) + { + return iter.seq_.t1; + } + }; + + template <typename Sq> + struct deref<triple_iterator<Sq, 1> const> + { + typedef typename Sq::t1_type const& type; + + static type + call(triple_iterator<Sq, 1> const& iter) + { + return iter.seq_.t1; + } + }; + + template <typename Sq> + struct deref<triple_iterator<Sq, 2> > + { + typedef typename Sq::t2_type& type; + + static type + call(triple_iterator<Sq, 2> const& iter) + { + return iter.seq_.t2; + } + }; + + template <typename Sq> + struct deref<triple_iterator<Sq, 2> const> + { + typedef typename Sq::t2_type const& type; + + static type + call(triple_iterator<Sq, 2> const& iter) + { + return iter.seq_.t2; + } + }; + + template<typename It> + struct next + { + typedef triple_iterator< + typename It::sequence_type, It::index::value + 1> + type; + + static type call(It const& it) + { + return type(it.seq_); + } + }; + + template<typename It> + struct prior + { + typedef triple_iterator< + typename It::sequence_type, It::index::value - 1> + type; + + static type call(It const& it) + { + return type(it.seq_); + } + }; + + template<typename It1, typename It2> + struct distance + { + typedef typename mpl::minus< + typename It2::index, typename It1::index>::type + type; + + static type call(It1 const& it1, It2 const& it2) + { + return type(); + } + }; + + template<typename It, typename M> + struct advance + { + typedef triple_iterator< + typename It::sequence_type, + It::index::value + M::value> + type; + + static type call(It const& it) + { + return type(it.seq_); + } + }; + }; + + template<typename T0, typename T1, typename T2> + struct triple + : fusion::sequence_facade<triple<T0, T1, T2>, + fusion::random_access_traversal_tag> + { + triple(T0 const& t0, T1 const& t1, T2 const& t2) + : t0(t0), t1(t1), t2(t2) + {} + + template<typename Sq> + struct begin + { + typedef demo::triple_iterator<Sq, 0> type; + + static type call(Sq& sq) + { + return type(sq); + } + }; + + template<typename Sq> + struct end + { + typedef demo::triple_iterator<Sq, 3> type; + + static type call(Sq& sq) + { + return type(sq); + } + }; + + template<typename Sq> + struct size + : mpl::int_<3> + {}; + + template<typename Sq, typename N> + struct value_at + : value_at<Sq, mpl::int_<N::value> > + {}; + + template<typename Sq> + struct value_at<Sq, mpl::int_<0> > + { + typedef typename Sq::t0_type type; + }; + + template<typename Sq> + struct value_at<Sq, mpl::int_<1> > + { + typedef typename Sq::t1_type type; + }; + + template<typename Sq> + struct value_at<Sq, mpl::int_<2> > + { + typedef typename Sq::t2_type type; + }; + + template<typename Sq, typename N> + struct at + : at<Sq, mpl::int_<N::value> > + {}; + + template<typename Sq> + struct at<Sq, mpl::int_<0> > + { + typedef typename + mpl::if_< + boost::is_const<Sq> + , typename Sq::t0_type const& + , typename Sq::t0_type& + >::type + type; + + static type call(Sq& sq) + { + return sq.t0; + } + }; + + template<typename Sq> + struct at<Sq, mpl::int_<1> > + { + typedef typename + mpl::if_< + boost::is_const<Sq> + , typename Sq::t1_type const& + , typename Sq::t1_type& + >::type + type; + + static type call(Sq& sq) + { + return sq.t1; + } + }; + + template<typename Sq> + struct at<Sq, mpl::int_<2> > + { + typedef typename + mpl::if_< + boost::is_const<Sq> + , typename Sq::t2_type const& + , typename Sq::t2_type& + >::type + type; + + static type call(Sq& sq) + { + return sq.t2; + } + }; + + typedef T0 t0_type; + typedef T1 t1_type; + typedef T2 t2_type; + + T0 t0; + T1 t1; + T2 t2; + }; +} + +struct modifying_fold_functor +{ + template <typename T> + struct result + { + typedef bool type; + }; + + template <typename T> + bool operator()(bool b, T&) + { + return b; + } +}; + +struct nonmodifying_fold_functor +{ + template <typename T> + struct result + { + typedef bool type; + }; + + template <typename T> + bool operator()(bool b, const T&) + { + return b; + } +}; + +int main() +{ + typedef demo::triple<int, char, std::string> my_triple; + my_triple t(101, 'a', "hello"); + BOOST_TEST(*fusion::begin(t) == 101); + BOOST_TEST(*fusion::next(fusion::begin(t)) == 'a'); + BOOST_TEST(*fusion::prior(fusion::end(t)) == "hello"); + BOOST_TEST(fusion::distance(fusion::begin(t), fusion::end(t)) == 3); + BOOST_TEST(fusion::size(t) == 3); + BOOST_MPL_ASSERT((boost::is_same< + int, fusion::result_of::value_at_c<my_triple, 0>::type>)); + BOOST_MPL_ASSERT((boost::is_same< + char, fusion::result_of::value_at_c<my_triple, 1>::type>)); + BOOST_MPL_ASSERT((boost::is_same< + std::string, fusion::result_of::value_at_c<my_triple, 2>::type>)); + BOOST_TEST(fusion::at_c<0>(t) == 101); + BOOST_TEST(fusion::at_c<1>(t) == 'a'); + BOOST_TEST(fusion::at_c<2>(t) == "hello"); + BOOST_TEST(fusion::fold(t, true, modifying_fold_functor()) == true); + BOOST_TEST(fusion::fold(t, true, nonmodifying_fold_functor()) == true); + return boost::report_errors(); +} diff --git a/src/boost/libs/fusion/example/performance/Jamfile b/src/boost/libs/fusion/example/performance/Jamfile new file mode 100644 index 00000000..3b8c8ffc --- /dev/null +++ b/src/boost/libs/fusion/example/performance/Jamfile @@ -0,0 +1,20 @@ +#============================================================================== +# Copyright (c) 2003-2006 Joel de Guzman +# Copyright (c) 2006 Dan Marsden +# +# 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) +#============================================================================== +project fusion-performance ; + +exe accumulate : accumulate.cpp ; + +exe inner_product : inner_product.cpp ; + +exe inner_product2 : inner_product2.cpp ; + +exe sequence_efficiency : sequence_efficiency.cpp ; + +exe functional : functional.cpp ; + diff --git a/src/boost/libs/fusion/example/performance/accumulate.cpp b/src/boost/libs/fusion/example/performance/accumulate.cpp new file mode 100644 index 00000000..176dc458 --- /dev/null +++ b/src/boost/libs/fusion/example/performance/accumulate.cpp @@ -0,0 +1,357 @@ +/*============================================================================= + 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) +==============================================================================*/ +#include <boost/array.hpp> +#include <boost/timer.hpp> + +#include <boost/fusion/algorithm/iteration/accumulate.hpp> +#include <boost/fusion/algorithm/transformation/transform.hpp> +#include <boost/fusion/container/vector.hpp> +#include <boost/fusion/algorithm/transformation/zip.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/fusion/adapted/array.hpp> + +#include <boost/type_traits/remove_reference.hpp> + +#include <algorithm> +#include <numeric> +#include <functional> +#include <iostream> +#include <cmath> +#include <limits> + +#ifdef _MSC_VER +// inline aggressively +# pragma inline_recursion(on) // turn on inline recursion +# pragma inline_depth(255) // max inline depth +#endif + +int const REPEAT_COUNT = 10; + +double const duration = 0.5; + +namespace +{ + template<int N> + double time_for_std_accumulate(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr; + std::generate(arr.begin(), arr.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::accumulate(arr.begin(), arr.end(), 0); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::accumulate(arr.begin(), arr.end(), 0); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } + + struct poly_add + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_add(Lhs,Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + Lhs operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs + rhs; + } + }; + + struct poly_mult + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_mult(Lhs, Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + Lhs operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs * rhs; + } + }; + + template<int N> + double time_for_fusion_accumulate(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr; + std::generate(arr.begin(), arr.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate(arr, 0, poly_add()); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + std::cout << iter << " iterations" << std::endl; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate(arr, 0, poly_add()); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + std::cout << "."; + std::cout.flush(); + } + std::cout << i << std::endl; + return result / iter; + } + +#if 0 + template<int N> + double time_for_std_inner_product(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr1; + boost::array<int, N> arr2; + std::generate(arr1.begin(), arr1.end(), rand); + std::generate(arr2.begin(), arr2.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } + + template<int N> + double time_for_fusion_inner_product(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr1; + boost::array<int, N> arr2; + std::generate(arr1.begin(), arr1.end(), rand); + std::generate(arr2.begin(), arr2.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add()); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add()); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } + + struct poly_combine + { + template<typename Lhs, typename Rhs> + struct result + { + typedef Lhs type; + }; + + template<typename Lhs, typename Rhs> + typename result<Lhs,Rhs>::type + operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs + boost::fusion::at_c<0>(rhs) * boost::fusion::at_c<1>(rhs); + } + }; + + template<int N> + double time_for_fusion_inner_product2(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr1; + boost::array<int, N> arr2; + std::generate(arr1.begin(), arr1.end(), rand); + std::generate(arr2.begin(), arr2.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::zip(arr1, arr2), 0, poly_combine()); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + std::cout << iter << " iterations" << std::endl; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::zip(arr1, arr2), 0, poly_combine()); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } +#endif +} + +int main() +{ + int total = 0; + int res; + std::cout << "short accumulate std test " << time_for_std_accumulate<8>(res) << std::endl; + total += res; + std::cout << "short accumulate fusion test " << time_for_fusion_accumulate<8>(res) << std::endl; + total += res; + + std::cout << "medium accumulate std test " << time_for_std_accumulate<64>(res) << std::endl; + total += res; + std::cout << "medium accumulate fusion test " << time_for_fusion_accumulate<64>(res) << std::endl; + total += res; + + std::cout << "long accumulate std test " << time_for_std_accumulate<128>(res) << std::endl; + total += res; + std::cout << "long accumulate fusion test " << time_for_fusion_accumulate<128>(res) << std::endl; + total += res; + +#if 0 + std::cout << "short inner_product std test " << time_for_std_inner_product<8>(res) << std::endl; + total += res; + std::cout << "short inner_product fusion test " << time_for_fusion_inner_product<8>(res) << std::endl; + total += res; + std::cout << "short inner_product fusion 2 test " << time_for_fusion_inner_product2<8>(res) << std::endl; + total += res; + + std::cout << "medium inner_product std test " << time_for_std_inner_product<64>(res) << std::endl; + total += res; + std::cout << "medium inner_product fusion test " << time_for_fusion_inner_product<64>(res) << std::endl; + total += res; + std::cout << "medium inner_product fusion 2 test " << time_for_fusion_inner_product2<64>(res) << std::endl; + total += res; + + + std::cout << "long inner_product std test " << time_for_std_inner_product<128>(res) << std::endl; + total += res; + std::cout << "long inner_product fusion test " << time_for_fusion_inner_product<128>(res) << std::endl; + total += res; + std::cout << "long inner_product fusion 2 test " << time_for_fusion_inner_product2<128>(res) << std::endl; + total += res; +#endif + + return total; +} diff --git a/src/boost/libs/fusion/example/performance/functional.cpp b/src/boost/libs/fusion/example/performance/functional.cpp new file mode 100644 index 00000000..9207a90d --- /dev/null +++ b/src/boost/libs/fusion/example/performance/functional.cpp @@ -0,0 +1,307 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are 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). +==============================================================================*/ + +#include <boost/fusion/container/list.hpp> +#include <boost/fusion/container/vector.hpp> +#include <boost/fusion/algorithm/iteration/fold.hpp> +#include <boost/fusion/functional/adapter/unfused.hpp> +#include <boost/fusion/functional/adapter/fused_function_object.hpp> + +#include <boost/functional/forward_adapter.hpp> +#include <boost/functional/lightweight_forward_adapter.hpp> + +#include <boost/utility/result_of.hpp> +#include <boost/config.hpp> +#include <boost/timer.hpp> +#include <algorithm> +#include <iostream> + +#ifdef _MSC_VER +// inline aggressively +# pragma inline_recursion(on) // turn on inline recursion +# pragma inline_depth(255) // max inline depth +#endif + +int const REPEAT_COUNT = 3; + +double const duration = 0.125; + + +namespace +{ + struct fused_sum + { + template <typename Seq> + int operator()(Seq const & seq) const + { + int state = 0; + return boost::fusion::fold(seq, state, sum_op()); + } + + typedef int result_type; + + private: + + struct sum_op + { + template <typename T> + int operator()(T const & elem, int value) const + { + return value + sizeof(T) * elem; + } + + template <typename T> + int operator()(T & elem, int value) const + { + elem += sizeof(T); + return value; + } + + typedef int result_type; + }; + }; + + struct unfused_sum + { + inline int operator()() const + { + return 0; + } + template<typename T0> + inline int operator()(T0 const & a0) const + { + return a0; + } + template<typename T0, typename T1> + inline int operator()(T0 const & a0, T1 const & a1) const + { + return a0 + a1; + } + template<typename T0, typename T1, typename T2> + inline int operator()(T0 const & a0, T1 const & a1, T2 a2) const + { + return a0 + a1 + a2; + } + template<typename T0, typename T1, typename T2, typename T3> + inline int operator()(T0 const & a0, T1 const & a1, T2 const & a2, T3 const & a3) const + { + return a0 + a1 + a2 + a3; + } + + typedef int result_type; + }; + + template<typename F> + double call_unfused(F const & func, int & j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i += func(); + i += func(0); + i += func(0,1); + i += func(0,1,2); + i += func(0,1,2,3); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = func(); j += i; + i = func(0); j += i; + i = func(0,1); j += i; + i = func(0,1,2); j += i; + i = func(0,1,2,3); j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + return result / iter; + } + + template<typename F> + double call_fused_ra(F const & func, int & j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + do + { + boost::fusion::vector<> v0; + boost::fusion::vector<int> v1(0); + boost::fusion::vector<int,int> v2(0,1); + boost::fusion::vector<int,int,int> v3(0,1,2); + boost::fusion::vector<int,int,int,int> v4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i += func(v0); + i += func(v1); + i += func(v2); + i += func(v3); + i += func(v4); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + boost::fusion::vector<> v0; + boost::fusion::vector<int> v1(0); + boost::fusion::vector<int,int> v2(0,1); + boost::fusion::vector<int,int,int> v3(0,1,2); + boost::fusion::vector<int,int,int,int> v4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = func(v0); j += i; + i = func(v1); j += i; + i = func(v2); j += i; + i = func(v3); j += i; + i = func(v4); j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + return result / iter; + } + + template<typename F> + double call_fused(F const & func, int & j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + do + { + boost::fusion::list<> l0; + boost::fusion::list<int> l1(0); + boost::fusion::list<int,int> l2(0,1); + boost::fusion::list<int,int,int> l3(0,1,2); + boost::fusion::list<int,int,int,int> l4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i += func(l0); + i += func(l1); + i += func(l2); + i += func(l3); + i += func(l4); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + boost::fusion::list<> l0; + boost::fusion::list<int> l1(0); + boost::fusion::list<int,int> l2(0,1); + boost::fusion::list<int,int,int> l3(0,1,2); + boost::fusion::list<int,int,int,int> l4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = func(l0); j += i; + i = func(l1); j += i; + i = func(l2); j += i; + i = func(l3); j += i; + i = func(l4); j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + return result / iter; + } +} + +int main() +{ + int total = 0; + int res; + typedef fused_sum F; + typedef unfused_sum U; + + std::cout << "Compiler: " << BOOST_COMPILER << std::endl; + std::cout << std::endl << "Unfused adapters:" << std::endl; + { + F f; + std::cout << "F /* a fused function object */ " << call_fused_ra(f,res) << std::endl; + total += res; + } + { + F f; + std::cout << "without random access " << call_fused(f,res) << std::endl; + total += res; + } + { + boost::lightweight_forward_adapter< boost::fusion::unfused<F> > f; + std::cout << "lightweight_forward_adapter< unfused<F> > " << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::forward_adapter< boost::fusion::unfused<F> > f; + std::cout << "forward_adapter< unfused<F> > " << call_unfused(f,res) << std::endl; + total += res; + } + std::cout << std::endl << "Fused adapters:" << std::endl; + { + unfused_sum f; + std::cout << "U /* an unfused function object */ " << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::fusion::fused_function_object<U> f; + std::cout << "fused_function_object<U> " << call_fused_ra(f,res) << std::endl; + total += res; + } + { + boost::fusion::fused_function_object<U> f; + std::cout << "without random access " << call_fused(f,res) << std::endl; + total += res; + } + { + boost::lightweight_forward_adapter< boost::fusion::unfused< boost::fusion::fused_function_object<U> > > f; + std::cout << "lightweight_forward_adapter< unfused<fused_function_object<U> > >" << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::forward_adapter< boost::fusion::unfused< boost::fusion::fused_function_object<U> > > f; + std::cout << "forward_adapter< unfused<fused_function_object<U> > > " << call_unfused(f,res) << std::endl; + total += res; + } + + return total; +} diff --git a/src/boost/libs/fusion/example/performance/inner_product.cpp b/src/boost/libs/fusion/example/performance/inner_product.cpp new file mode 100644 index 00000000..c9f22c7c --- /dev/null +++ b/src/boost/libs/fusion/example/performance/inner_product.cpp @@ -0,0 +1,184 @@ +/*============================================================================= + 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) +==============================================================================*/ +#include <boost/array.hpp> +#include <boost/timer.hpp> + +#include <boost/fusion/algorithm/iteration/accumulate.hpp> +#include <boost/fusion/algorithm/transformation/transform.hpp> +#include <boost/fusion/container/vector.hpp> +#include <boost/fusion/algorithm/transformation/zip.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/fusion/adapted/array.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> + +#include <boost/type_traits/remove_reference.hpp> + +#include <algorithm> +#include <numeric> +#include <functional> +#include <iostream> +#include <cmath> +#include <limits> + +#ifdef _MSC_VER +// inline aggressively +# pragma inline_recursion(on) // turn on inline recursion +# pragma inline_depth(255) // max inline depth +#endif + +int const REPEAT_COUNT = 10; + +double const duration = 0.5; + +namespace +{ + struct poly_add + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_add(Lhs, Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + Lhs operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs + rhs; + } + }; + + struct poly_mult + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_mult(Lhs, Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + Lhs operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs * rhs; + } + }; + + template<int N> + double time_for_std_inner_product(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr1; + boost::array<int, N> arr2; + std::generate(arr1.begin(), arr1.end(), rand); + std::generate(arr2.begin(), arr2.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } + + template<int N> + double time_for_fusion_inner_product(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr1; + boost::array<int, N> arr2; + std::generate(arr1.begin(), arr1.end(), rand); + std::generate(arr2.begin(), arr2.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add()); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add()); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } +} + +int main() +{ + int total = 0; + int res; + + std::cout << "short inner_product std test " << time_for_std_inner_product<8>(res) << std::endl; + total += res; + std::cout << "short inner_product fusion test " << time_for_fusion_inner_product<8>(res) << std::endl; + total += res; + + std::cout << "medium inner_product std test " << time_for_std_inner_product<64>(res) << std::endl; + total += res; + std::cout << "medium inner_product fusion test " << time_for_fusion_inner_product<64>(res) << std::endl; + total += res; + + std::cout << "long inner_product std test " << time_for_std_inner_product<128>(res) << std::endl; + total += res; + std::cout << "long inner_product fusion test " << time_for_fusion_inner_product<128>(res) << std::endl; + total += res; + + return total; +} diff --git a/src/boost/libs/fusion/example/performance/inner_product2.cpp b/src/boost/libs/fusion/example/performance/inner_product2.cpp new file mode 100644 index 00000000..f1d536af --- /dev/null +++ b/src/boost/libs/fusion/example/performance/inner_product2.cpp @@ -0,0 +1,206 @@ +/*============================================================================= + 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) +==============================================================================*/ +#include <boost/array.hpp> +#include <boost/timer.hpp> + +#include <boost/fusion/algorithm/iteration/accumulate.hpp> +#include <boost/fusion/algorithm/transformation/transform.hpp> +#include <boost/fusion/container/vector.hpp> +#include <boost/fusion/algorithm/transformation/zip.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/fusion/adapted/array.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> + +#include <boost/type_traits/remove_reference.hpp> + +#include <algorithm> +#include <numeric> +#include <functional> +#include <iostream> +#include <cmath> +#include <limits> + +#ifdef _MSC_VER +// inline aggressively +# pragma inline_recursion(on) // turn on inline recursion +# pragma inline_depth(255) // max inline depth +#endif + +int const REPEAT_COUNT = 10; + +double const duration = 0.5; + +namespace +{ + struct poly_add + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_add(Lhs, Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + Lhs operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs + rhs; + } + }; + + struct poly_mult + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_mult(Lhs, Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + Lhs operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs * rhs; + } + }; + + template<int N> + double time_for_std_inner_product(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr1; + boost::array<int, N> arr2; + std::generate(arr1.begin(), arr1.end(), rand); + std::generate(arr2.begin(), arr2.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } + + struct poly_combine + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_combine(Lhs, Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + typename result<poly_combine(Lhs,Rhs)>::type + operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs + boost::fusion::at_c<0>(rhs) * boost::fusion::at_c<1>(rhs); + } + }; + + template<int N> + double time_for_fusion_inner_product2(int& j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits<double>::max)(); + double runtime = 0; + double run; + boost::array<int, N> arr1; + boost::array<int, N> arr2; + std::generate(arr1.begin(), arr1.end(), rand); + std::generate(arr2.begin(), arr2.end(), rand); + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::zip(arr1, arr2), 0, poly_combine()); + static_cast<void>(i); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + std::cout << iter << " iterations" << std::endl; + + // repeat test and report least value for consistency: + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = boost::fusion::accumulate( + boost::fusion::zip(arr1, arr2), 0, poly_combine()); + j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + std::cout << i << std::endl; + return result / iter; + } +} + +int main() +{ + int total = 0; + int res; + + std::cout << "short inner_product std test " << time_for_std_inner_product<8>(res) << std::endl; + total += res; + std::cout << "short inner_product fusion 2 test " << time_for_fusion_inner_product2<8>(res) << std::endl; + total += res; + + std::cout << "medium inner_product std test " << time_for_std_inner_product<64>(res) << std::endl; + total += res; + std::cout << "medium inner_product fusion 2 test " << time_for_fusion_inner_product2<64>(res) << std::endl; + total += res; + +#if 0 // Leads to ICE with MSVC 8.0 + std::cout << "long inner_product std test " << time_for_std_inner_product<128>(res) << std::endl; + total += res; + std::cout << "long inner_product fusion 2 test " << time_for_fusion_inner_product2<128>(res) << std::endl; + total += res; +#endif + + return total; +} diff --git a/src/boost/libs/fusion/example/performance/measure.hpp b/src/boost/libs/fusion/example/performance/measure.hpp new file mode 100644 index 00000000..72cd71ba --- /dev/null +++ b/src/boost/libs/fusion/example/performance/measure.hpp @@ -0,0 +1,85 @@ +// Copyright David Abrahams, Matthias Troyer, Michael Gauckler +// 2005. 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(LIVE_CODE_TYPE) +# define LIVE_CODE_TYPE int +#endif + +#include <boost/timer.hpp> + +namespace test +{ + // This value is required to ensure that a smart compiler's dead + // code elimination doesn't optimize away anything we're testing. + // We'll use it to compute the return code of the executable to make + // sure it's needed. + LIVE_CODE_TYPE live_code; + + // Call objects of the given Accumulator type repeatedly with x as + // an argument. + template <class Accumulator, class Arg> + void hammer(Arg const& x, long const repeats) + { + // Strategy: because the sum in an accumulator after each call + // depends on the previous value of the sum, the CPU's pipeline + // might be stalled while waiting for the previous addition to + // complete. Therefore, we allocate an array of accumulators, + // and update them in sequence, so that there's no dependency + // between adjacent addition operations. + // + // Additionally, if there were only one accumulator, the + // compiler or CPU might decide to update the value in a + // register rather that writing it back to memory. we want each + // operation to at least update the L1 cache. *** Note: This + // concern is specific to the particular application at which + // we're targeting the test. *** + + // This has to be at least as large as the number of + // simultaneous accumulations that can be executing in the + // compiler pipeline. A safe number here is larger than the + // machine's maximum pipeline depth. If you want to test the L2 + // or L3 cache, or main memory, you can increase the size of + // this array. 1024 is an upper limit on the pipeline depth of + // current vector machines. + const std::size_t number_of_accumulators = 1024; + live_code = 0; // reset to zero + + Accumulator a[number_of_accumulators]; + + for (long iteration = 0; iteration < repeats; ++iteration) + { + for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap) + { + (*ap)(x); + } + } + + // Accumulate all the partial sums to avoid dead code + // elimination. + for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap) + { + live_code += ap->sum; + } + } + + // Measure the time required to hammer accumulators of the given + // type with the argument x. + template <class Accumulator, class T> + double measure(T const& x, long const repeats) + { + // Hammer accumulators a couple of times to ensure the + // instruction cache is full of our test code, and that we don't + // measure the cost of a page fault for accessing the data page + // containing the memory where the accumulators will be + // allocated + hammer<Accumulator>(x, repeats); + hammer<Accumulator>(x, repeats); + + // Now start a timer + boost::timer time; + hammer<Accumulator>(x, repeats); // This time, we'll measure + return time.elapsed() / repeats; // return the time of one iteration + } +} diff --git a/src/boost/libs/fusion/example/performance/sequence_efficiency.cpp b/src/boost/libs/fusion/example/performance/sequence_efficiency.cpp new file mode 100644 index 00000000..307ecdf3 --- /dev/null +++ b/src/boost/libs/fusion/example/performance/sequence_efficiency.cpp @@ -0,0 +1,248 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + + 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 "measure.hpp" + +#define FUSION_MAX_LIST_SIZE 30 +#define FUSION_MAX_VECTOR_SIZE 30 + +#include <boost/fusion/algorithm/iteration/accumulate.hpp> +#include <boost/fusion/container/vector.hpp> +#include <boost/fusion/container/list.hpp> + +#include <boost/type_traits/remove_reference.hpp> + +#include <boost/lexical_cast.hpp> +#include <boost/preprocessor/stringize.hpp> +#include <boost/preprocessor/enum.hpp> + +#include <iostream> + +#ifdef _MSC_VER +// inline aggressively +# pragma inline_recursion(on) // turn on inline recursion +# pragma inline_depth(255) // max inline depth +#endif + +// About the tests: +// +// The tests below compare various fusion sequences to see how abstraction +// affects prformance. +// +// We have 3 sequence sizes for each fusion sequence we're going to test. +// +// small = 3 elements +// medium = 10 elements +// big = 30 elements +// +// The sequences are initialized with values 0..N-1 from numeric strings +// parsed by boost::lexical_cast to make sure that the compiler is not +// optimizing by replacing the computation with constant results computed +// at compile time. +// +// These sequences will be subjected to our accumulator which calls +// fusion::accumulate: +// +// this->sum += boost::fusion::accumulate(seq, 0, poly_add()); +// +// where poly_add simply sums the current value with the content of +// the sequence element. This accumulator will be called many times +// through the "hammer" test (see measure.hpp). +// +// The tests are compared against a base using a plain_accumulator +// which does a simple addition: +// +// this->sum += x; + +namespace +{ + struct poly_add + { + template<typename Sig> + struct result; + + template<typename Lhs, typename Rhs> + struct result<poly_add(Lhs, Rhs)> + : boost::remove_reference<Lhs> + {}; + + template<typename Lhs, typename Rhs> + Lhs operator()(const Lhs& lhs, const Rhs& rhs) const + { + return lhs + rhs; + } + }; + + // Our Accumulator function + template <typename T> + struct accumulator + { + accumulator() + : sum() + {} + + template <typename Sequence> + void operator()(Sequence const& seq) + { + this->sum += boost::fusion::accumulate(seq, 0, poly_add()); + } + + T sum; + }; + + // Plain Accumulator function + template <typename T> + struct plain_accumulator + { + plain_accumulator() + : sum() + {} + + template <typename X> + void operator()(X const& x) + { + this->sum += x; + } + + T sum; + }; + + template <typename T> + void check(T const& seq, char const* info) + { + test::measure<accumulator<int> >(seq, 1); + std::cout << info << test::live_code << std::endl; + } + + template <typename T> + void measure(T const& seq, char const* info, long const repeats, double base) + { + double t = test::measure<accumulator<int> >(seq, repeats); + std::cout + << info + << t + << " (" << int((t/base)*100) << "%)" + << std::endl; + } + + template <typename T> + void test_assembler(T const& seq) + { + test::live_code = boost::fusion::accumulate(seq, 0, poly_add()); + } +} + +// We'll initialize the sequences from numeric strings that +// pass through boost::lexical_cast to make sure that the +// compiler is not optimizing by replacing the computation +// with constant results computed at compile time. +#define INIT(z, n, text) boost::lexical_cast<int>(BOOST_PP_STRINGIZE(n)) + +int main() +{ + using namespace boost::fusion; + std::cout.setf(std::ios::scientific); + + vector< + int, int, int + > + vsmall(BOOST_PP_ENUM(3, INIT, _)); + + list< + int, int, int + > + lsmall(BOOST_PP_ENUM(3, INIT, _)); + + vector< + int, int, int, int, int, int, int, int, int, int + > + vmedium(BOOST_PP_ENUM(10, INIT, _)); + + list< + int, int, int, int, int, int, int, int, int, int + > + lmedium(BOOST_PP_ENUM(10, INIT, _)); + + vector< + int, int, int, int, int, int, int, int, int, int + , int, int, int, int, int, int, int, int, int, int + , int, int, int, int, int, int, int, int, int, int + > + vbig(BOOST_PP_ENUM(30, INIT, _)); + + list< + int, int, int, int, int, int, int, int, int, int + , int, int, int, int, int, int, int, int, int, int + , int, int, int, int, int, int, int, int, int, int + > + lbig(BOOST_PP_ENUM(30, INIT, _)); + + // first decide how many repetitions to measure + long repeats = 100; + double measured = 0; + while (measured < 2.0 && repeats <= 10000000) + { + repeats *= 10; + + boost::timer time; + + test::hammer<plain_accumulator<int> >(0, repeats); + test::hammer<accumulator<int> >(vsmall, repeats); + test::hammer<accumulator<int> >(lsmall, repeats); + test::hammer<accumulator<int> >(vmedium, repeats); + test::hammer<accumulator<int> >(lmedium, repeats); + test::hammer<accumulator<int> >(vbig, repeats); + test::hammer<accumulator<int> >(lbig, repeats); + + measured = time.elapsed(); + } + + test::measure<plain_accumulator<int> >(1, 1); + std::cout + << "base accumulated result: " + << test::live_code + << std::endl; + + double base_time = test::measure<plain_accumulator<int> >(1, repeats); + std::cout + << "base time: " + << base_time; + + std::cout + << std::endl + << "-------------------------------------------------------------------" + << std::endl; + + check(vsmall, "small vector accumulated result: "); + check(lsmall, "small list accumulated result: "); + check(vmedium, "medium vector accumulated result: "); + check(lmedium, "medium list accumulated result: "); + check(vbig, "big vector accumulated result: "); + check(lbig, "big list accumulated result: "); + + std::cout + << "-------------------------------------------------------------------" + << std::endl; + + measure(vsmall, "small vector time: ", repeats, base_time); + measure(lsmall, "small list time: ", repeats, base_time); + measure(vmedium, "medium vector time: ", repeats, base_time); + measure(lmedium, "medium list time: ", repeats, base_time); + measure(vbig, "big vector time: ", repeats, base_time); + measure(lbig, "big list time: ", repeats, base_time); + + std::cout + << "-------------------------------------------------------------------" + << std::endl; + + // Let's see how this looks in assembler + test_assembler(vmedium); + + // This is ultimately responsible for preventing all the test code + // from being optimized away. Change this to return 0 and you + // unplug the whole test's life support system. + return test::live_code != 0; +} diff --git a/src/boost/libs/fusion/example/performance/timings.txt b/src/boost/libs/fusion/example/performance/timings.txt new file mode 100644 index 00000000..35549170 --- /dev/null +++ b/src/boost/libs/fusion/example/performance/timings.txt @@ -0,0 +1,57 @@ +=============================================================================== +Copyright (C) 2001-2007 Joel de Guzman, Dan Marsden, Tobias Schwinger + +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) +=============================================================================== + +Timing result for sequence_efficiency.cpp comparing the speed of various +fusion sequences. The test involves accumulating the elements of the +sequence which is primed to have values 0..N (N=size of sequence). Small, +medium and big sequences are tested where: + + small = 3 elements + medium = 10 elements + big = 30 elements + +Tester: Joel de Guzman. WinXP, P4-3.0GHZ, 2GB RAM + +VC7.1 (flags = /MD /O2 /EHsc /GS) + + small vector time: 1.870000e-006 + small list time: 1.870000e-006 + medium vector time: 1.880000e-006 + medium list time: 3.600000e-006 + big vector time: 2.030000e-006 + big list time: 8.910000e-006 + +VC8.0 (flags = /MD /O2 /EHsc /GS) + + small vector time: 2.500000e-05 + small list time: 2.500000e-05 + medium vector time: 7.810000e-05 + medium list time: 7.810000e-05 + big vector time: 2.469000e-04 + big list time: 2.453000e-04 + +G++ 3.4 (flags = -ftemplate-depth-128 -funroll-loops -O3 -finline-functions -Wno-inline -Wall) + + small vector time: 2.500000e-05 + small list time: 2.500000e-05 + medium vector time: 7.970000e-05 + medium list time: 7.970000e-05 + big vector time: 2.516000e-04 + big list time: 2.485000e-04 + +Intel 9.1 (flags = /MD /O2 /EHsc /GS) + + small vector time: 1.125000e-006 + small list time: 1.125000e-006 + medium vector time: 1.125000e-006 + medium list time: 1.141000e-006 + big vector time: 1.140000e-006 + big list time: 1.141000e-006 + + + diff --git a/src/boost/libs/fusion/example/performance/zip_efficiency.cpp b/src/boost/libs/fusion/example/performance/zip_efficiency.cpp new file mode 100644 index 00000000..6d240f2c --- /dev/null +++ b/src/boost/libs/fusion/example/performance/zip_efficiency.cpp @@ -0,0 +1,155 @@ +/*============================================================================= + Copyright (c) 2001-2011 Joel de Guzman + + 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 "measure.hpp" + +//~ #define FUSION_MAX_VECTOR_SIZE 30 + +#include <boost/fusion/algorithm/iteration/accumulate.hpp> +#include <boost/fusion/algorithm/transformation/zip.hpp> +#include <boost/fusion/container/vector.hpp> +#include <boost/fusion/sequence/intrinsic/value_at.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <iostream> + +#ifdef _MSC_VER +// inline aggressively +# pragma inline_recursion(on) // turn on inline recursion +# pragma inline_depth(255) // max inline depth +#endif + +namespace +{ + struct zip_add + { + template<typename Lhs, typename Rhs> + struct result + { + typedef typename + boost::remove_reference< + typename boost::fusion::result_of::value_at_c<Lhs, 0>::type + >::type + type; + }; + + template<typename Lhs, typename Rhs> + typename result<Lhs, Rhs>::type + operator()(const Lhs& lhs, const Rhs& rhs) const + { + return boost::fusion::at_c<0>(lhs) + boost::fusion::at_c<1>(lhs) + rhs; + } + }; + + // Our Accumulator function + template <typename T> + struct zip_accumulator + { + zip_accumulator() + : sum() + {} + + template <typename Sequence> + void operator()(Sequence const& seq) + { + this->sum += boost::fusion::accumulate(seq, 0, zip_add()); + } + + T sum; + }; + + template <typename T> + void check(T const& seq, char const* info) + { + test::measure<zip_accumulator<int> >(seq, 1); + std::cout << info << test::live_code << std::endl; + } + + template <typename T> + void measure(T const& seq, char const* info, long const repeats) + { + std::cout + << info + << test::measure<zip_accumulator<int> >(seq, repeats) + << std::endl; + } +} + +int main() +{ + using namespace boost::fusion; + + std::cout.setf(std::ios::scientific); + + vector< + int, int, int + > + vsmall_1(BOOST_PP_ENUM_PARAMS(3,)); + + vector< + int, int, int + > + vsmall_2(BOOST_PP_ENUM_PARAMS(3,)); + + vector< + int, int, int, int, int, int, int, int, int, int + > + vmedium_1(BOOST_PP_ENUM_PARAMS(10,)); + + vector< + int, int, int, int, int, int, int, int, int, int + > + vmedium_2(BOOST_PP_ENUM_PARAMS(10,)); + + //~ vector< + //~ int, int, int, int, int, int, int, int, int, int + //~ , int, int, int, int, int, int, int, int, int, int + //~ , int, int, int, int, int, int, int, int, int, int + //~ > + //~ vbig_1(BOOST_PP_ENUM_PARAMS(30,)); + + //~ vector< + //~ int, int, int, int, int, int, int, int, int, int + //~ , int, int, int, int, int, int, int, int, int, int + //~ , int, int, int, int, int, int, int, int, int, int + //~ > + //~ vbig_2(BOOST_PP_ENUM_PARAMS(30,)); + + // first decide how many repetitions to measure + long repeats = 100; + double measured = 0; + while (measured < 2.0 && repeats <= 10000000) + { + repeats *= 10; + + boost::timer time; + + test::hammer<zip_accumulator<int> >(zip(vsmall_1, vsmall_2), repeats); + test::hammer<zip_accumulator<int> >(zip(vmedium_1, vmedium_2), repeats); + //~ test::hammer<zip_accumulator<int> >(zip(vbig_1, vbig_2), repeats); + + measured = time.elapsed(); + } + + check(zip(vsmall_1, vsmall_2), + "small zip accumulated result: "); + check(zip(vmedium_1, vmedium_2), + "medium zip accumulated result: "); + //~ check(zip(vbig_1, vbig_2), + //~ "big zip accumulated result: "); + + measure(zip(vsmall_1, vsmall_2), + "small zip time: ", repeats); + measure(zip(vmedium_1, vmedium_2), + "medium zip time: ", repeats); + //~ measure(zip(vbig_1, vbig_2), + //~ "big zip time: ", repeats); + + // This is ultimately responsible for preventing all the test code + // from being optimized away. Change this to return 0 and you + // unplug the whole test's life support system. + return test::live_code != 0; +} |