mirror of
https://github.com/boostorg/fusion.git
synced 2025-07-29 12:07:36 +02:00
Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
This commit is contained in:
@ -1,237 +0,0 @@
|
||||
/*=============================================================================
|
||||
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_generic.hpp>
|
||||
#include <boost/fusion/functional/adapter/unfused_rvalue_args.hpp>
|
||||
#include <boost/fusion/support/deduce_sequence.hpp>
|
||||
|
||||
#include <boost/fusion/sequence/intrinsic/at.hpp>
|
||||
#include <boost/fusion/mpl.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/front.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/empty.hpp>
|
||||
#include <boost/fusion/algorithm/transformation/transform.hpp>
|
||||
#include <boost/fusion/algorithm/transformation/pop_front.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/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
|
||||
{
|
||||
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
|
||||
|
||||
};
|
||||
|
||||
// Fused implementation of the 'bind' function
|
||||
struct fused_binder
|
||||
{
|
||||
template <class Signature>
|
||||
struct result;
|
||||
|
||||
template <class BindArgs>
|
||||
struct result_impl
|
||||
{
|
||||
// We have to transform the arguments so they are held by-value
|
||||
// in the returned function.
|
||||
typedef fusion::unfused_generic<
|
||||
fused_bound_function<BindArgs> > 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(bind_args);
|
||||
}
|
||||
};
|
||||
|
||||
// The binder's unfused type. We use unfused_rvalue_args to make that
|
||||
// thing more similar to Boost.Bind. Because of that we have to use
|
||||
// Boost.Ref (below in the sample code)
|
||||
typedef fusion::unfused_rvalue_args<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_)(value) == 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;
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2006 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;
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
#==============================================================================
|
||||
# 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 : : : : ]
|
||||
;
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,67 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,72 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,43 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,34 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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_sequence_tag {};
|
||||
};
|
||||
};
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
@ -1,67 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,44 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,43 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,38 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,45 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,34 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,32 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,46 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,46 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,36 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,44 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,50 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,49 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,25 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,64 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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/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"
|
||||
|
||||
namespace example
|
||||
{
|
||||
struct example_struct_iterator_tag;
|
||||
|
||||
template<typename Struct, int Pos>
|
||||
struct example_struct_iterator;
|
||||
}
|
||||
|
||||
namespace boost { namespace fusion {
|
||||
|
||||
struct random_access_traversal_tag;
|
||||
|
||||
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;
|
||||
typedef boost::fusion::random_access_traversal_tag category;
|
||||
|
||||
example_struct_iterator(Struct& str)
|
||||
: struct_(str) {}
|
||||
|
||||
Struct& struct_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,27 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,30 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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
|
@ -1,62 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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(size(bert) == 2);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,319 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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)
|
||||
==============================================================================*/
|
||||
|
||||
/*=============================================================================
|
||||
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/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
|
||||
mpl::if_<
|
||||
boost::is_const<Sq>
|
||||
, typename Sq::t0_type const&
|
||||
, typename Sq::t0_type&
|
||||
>::type
|
||||
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
|
||||
mpl::if_<
|
||||
boost::is_const<Sq>
|
||||
, typename Sq::t1_type const&
|
||||
, typename Sq::t1_type&
|
||||
>::type
|
||||
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
|
||||
mpl::if_<
|
||||
boost::is_const<Sq>
|
||||
, typename Sq::t2_type const&
|
||||
, typename Sq::t2_type&
|
||||
>::type
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
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");
|
||||
return boost::report_errors();
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#==============================================================================
|
||||
# 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 ;
|
||||
|
@ -1,357 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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 Rhs type;
|
||||
};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
typename result<Lhs,Rhs>::type
|
||||
operator()(const Lhs& lhs, const Rhs& rhs) const
|
||||
{
|
||||
return rhs + boost::fusion::at_c<0>(lhs) * boost::fusion::at_c<1>(lhs);
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
@ -1,305 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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_generic.hpp>
|
||||
#include <boost/fusion/functional/adapter/unfused_rvalue_args.hpp>
|
||||
#include <boost/fusion/functional/adapter/fused_function_object.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::fusion::unfused_rvalue_args<F> f;
|
||||
std::cout << "unfused_rvalue_args<F> " << call_unfused(f,res) << std::endl;
|
||||
total += res;
|
||||
}
|
||||
{
|
||||
boost::fusion::unfused_generic<F> f;
|
||||
std::cout << "unfused_generic<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::fusion::unfused_rvalue_args< boost::fusion::fused_function_object<U> > f;
|
||||
std::cout << "unfused_rvalue_args<fused_function_object<U> > " << call_unfused(f,res) << std::endl;
|
||||
total += res;
|
||||
}
|
||||
{
|
||||
boost::fusion::unfused_generic< boost::fusion::fused_function_object<U> > f;
|
||||
std::cout << "unfused_generic<fused_function_object<U> > " << call_unfused(f,res) << std::endl;
|
||||
total += res;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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;
|
||||
}
|
@ -1,206 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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<Rhs>
|
||||
{};
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
typename result<poly_combine(Lhs,Rhs)>::type
|
||||
operator()(const Lhs& lhs, const Rhs& rhs) const
|
||||
{
|
||||
return rhs + boost::fusion::at_c<0>(lhs) * boost::fusion::at_c<1>(lhs);
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
// 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
|
||||
}
|
||||
}
|
@ -1,248 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
===============================================================================
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,155 +0,0 @@
|
||||
/*=============================================================================
|
||||
Copyright (c) 2001-2006 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;
|
||||
}
|
Reference in New Issue
Block a user