diff --git a/README b/README index c36d06e1..78821c40 100644 --- a/README +++ b/README @@ -75,13 +75,20 @@ constexpr レイトレーシング このマクロが定義されているとき、関数は noexcept 修飾されない。 コンパイラが noexcept に対応していない場合。 +#define SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES +このマクロが定義されているとき、Template Aliases によるエイリアスは定義されない。 +コンパイラが Template Aliases に対応していない場合。 + #define SPROUT_CONFIG_USE_SSCRISK_CEL このマクロが定義されているとき、実装の詳細として CEL - ConstExpr Library を使用する。 https://github.com/sscrisk/CEL---ConstExpr-Library +#define SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION +このマクロが定義されているとき、アルゴリズムへのコンテナの一時オブジェクトを渡しをサポートしない。 +なおその場合、Sprout のコンテナのイテレータはポインタになる。 + #define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION -このマクロが定義されているとき、GCC4.7 において、アルゴリズムにコンテナの一時オブジェクトを渡せない問題を回避する。 -なおその場合、Sprout のコンテナのイテレータはポインタではなくなる。 +このマクロは非推奨です。 これらのマクロをユーザ定義する場合、このライブラリのどのヘッダがインクルードされるよりも先に定義されなければならない。 diff --git a/sprout/auto_config.hpp b/sprout/auto_config.hpp index 8e5f0343..cfb54dda 100644 --- a/sprout/auto_config.hpp +++ b/sprout/auto_config.hpp @@ -27,16 +27,29 @@ # endif // #ifdef BOOST_NO_NOEXCEPT #endif // #ifndef SPROUT_CONFIG_DISABLE_NOEXCEPT +// +// SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES +// +#ifndef SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES +# ifdef BOOST_NO_TEMPLATE_ALIASES +# if !defined(__GNUC__) \ + || defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) || !defined(__GXX_EXPERIMENTAL_CXX0X__)) +# define SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES +# endif +# endif // #ifdef BOOST_NO_TEMPLATE_ALIASES +#endif // #ifndef SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES + // // SPROUT_CONFIG_USE_SSCRISK_CEL // // +// SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION // SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION // -#ifndef SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION +#ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION # define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION -#endif // #ifndef SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION +#endif // #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION #include diff --git a/sprout/breed/args.hpp b/sprout/breed/args.hpp new file mode 100644 index 00000000..5783369c --- /dev/null +++ b/sprout/breed/args.hpp @@ -0,0 +1,128 @@ +#ifndef SPROUT_BREED_ARGS_HPP +#define SPROUT_BREED_ARGS_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template + struct ref_only + : public std::integral_constant< + bool, + std::is_function::value + > + {}; + + template + struct expr_traits { + public: + typedef Expr value_type; + typedef Expr& reference; + typedef Expr const& const_reference; + }; + template + struct expr_traits { + public: + typedef Expr value_type; + typedef Expr& reference; + typedef Expr& const_reference; + }; + template + struct expr_traits { + public: + typedef Expr value_type; + typedef Expr const& reference; + typedef Expr const& const_reference; + }; + + template + struct term_traits { + public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + }; + template + struct term_traits { + public: + typedef typename std::conditional::value, T&, T>::type value_type; + typedef T& reference; + typedef T& const_reference; + }; + template + struct term_traits { + public: + typedef T value_type; + typedef T const& reference; + typedef T const& const_reference; + }; + template + struct term_traits { + public: + typedef T value_type[N]; + typedef T (&reference)[N]; + typedef T (&const_reference)[N]; + }; + template + struct term_traits { + public: + typedef T value_type[N]; + typedef T const (&reference)[N]; + typedef T const (&const_reference)[N]; + }; + template + struct term_traits { + public: + typedef T value_type[N]; + typedef T (&reference)[N]; + typedef T const (&const_reference)[N]; + }; + template + struct term_traits { + public: + typedef T value_type[N]; + typedef T const (&reference)[N]; + typedef T const (&const_reference)[N]; + }; + } // namespace detail + + namespace argsns_ { + // + // term + // + template + struct term { + public: + SPROUT_STATIC_CONSTEXPR long arity = 0; + public: + template + struct child + : public sprout::tppack_at + {}; + public: + typedef Arg back_; + }; + // + // list + // + template + struct list { + public: + SPROUT_STATIC_CONSTEXPR long arity = sizeof...(Args); + public: + template + struct child + : public sprout::tppack_at + {}; + public: + typedef typename child::type back_; + }; + } // namespace argsns_ { + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_ARGS_HPP diff --git a/sprout/breed/breed.hpp b/sprout/breed/breed.hpp new file mode 100644 index 00000000..936ffc80 --- /dev/null +++ b/sprout/breed/breed.hpp @@ -0,0 +1,10 @@ +#ifndef SPROUT_BREED_BREED_HPP +#define SPROUT_BREED_BREED_HPP + +#include +//#include +//#include +//#include +//#include + +#endif // #ifndef SPROUT_BREED_BREED_HPP diff --git a/sprout/breed/breed_fwd.hpp b/sprout/breed/breed_fwd.hpp new file mode 100644 index 00000000..44b93632 --- /dev/null +++ b/sprout/breed/breed_fwd.hpp @@ -0,0 +1,707 @@ +#ifndef SPROUT_BREED_BREED_FWD_HPP +#define SPROUT_BREED_BREED_FWD_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + typedef char yes_type; + typedef char (&no_type)[2]; + + template + struct sized_type { + public: + typedef char (&type)[N]; + }; + + struct dont_care; + struct undefined; + struct not_a_valid_type; + + struct private_type_ { + public: + SPROUT_CONSTEXPR private_type_ operator,(int) const; //!!!! + }; + + template + struct uncvref { + public: + typedef T type; + }; + template + struct uncvref { + public: + typedef T type; + }; + template + struct uncvref { + public: + typedef T type; + }; + template + struct uncvref { + public: + typedef T type; + }; + template + struct uncvref { + public: + typedef T type[N]; + }; + template + struct uncvref { + public: + typedef T type[N]; + }; + template + struct uncvref { + public: + typedef T type[N]; + }; + + struct ignore { + public: + ignore() = default; + ignore(ignore const&) = default; + ignore(ignore&&) = default; + template + SPROUT_CONSTEXPR ignore(T const&) {} + }; + + struct _default; + + struct not_a_domain; + struct not_a_grammar; + struct not_a_generator; + + template + struct is_transform_; + + template + struct is_aggregate_; + } // namespace detail + + typedef sprout::breed::detail::ignore const ignore; + + namespace argsns_ { + template + struct term; + + template + struct list; + } // namespace argsns_ + using namespace argsns_; + + namespace tagns_ { + namespace tag { + struct terminal; + struct unary_plus; + struct negate; + struct dereference; + struct complement; + struct address_of; + struct logical_not; + struct pre_inc; + struct pre_dec; + struct post_inc; + struct post_dec; + + struct shift_left; + struct shift_right; + struct multiplies; + struct divides; + struct modulus; + struct plus; + struct minus; + struct less; + struct greater; + struct less_equal; + struct greater_equal; + struct equal_to; + struct not_equal_to; + struct logical_or; + struct logical_and; + struct bitwise_and; + struct bitwise_or; + struct bitwise_xor; + struct comma; + struct mem_ptr; + + struct assign; + struct shift_left_assign; + struct shift_right_assign; + struct multiplies_assign; + struct divides_assign; + struct modulus_assign; + struct plus_assign; + struct minus_assign; + struct bitwise_and_assign; + struct bitwise_or_assign; + struct bitwise_xor_assign; + struct subscript; + struct member; + struct if_else_; + struct function; + + // Fusion tags + struct breed_expr; + struct breed_expr_iterator; + struct breed_flat_view; + } // namespace tag + } // namespace tagns_ + using namespace tagns_; + + template + struct tag_of; + + struct _; + + struct default_generator; + + struct basic_default_generator; + + template class Extends> + struct generator; + + template class Extends> + struct pod_generator; + + struct by_value_generator; + + template + struct compose_generators; + + template + struct wants_basic_expr; + + template + struct use_basic_expr; + + namespace domainns_ { + typedef sprout::breed::detail::not_a_domain no_super_domain; + + template< + typename Generator = sprout::breed::default_generator, + typename Grammar = sprout::breed::_, + typename Super = sprout::breed::domainns_::no_super_domain + > + struct domain; + + struct default_domain; + + struct basic_default_domain; + + struct deduce_domain; + + template< + typename Domain, + typename Tag, + typename Args, + bool WantsBasicExpr = sprout::breed::wants_basic_expr::value + > + struct base_expr; + } // namespace domainns_ + using namespace domainns_; + + namespace exprns_ { + template + struct basic_expr; + + template + struct expr; + + template< + typename Expr, + typename Derived, + typename Domain = sprout::breed::default_domain, + long Arity = Expr::breed_arity_c + > + struct extends; + + template + struct virtual_member; + + struct is_breed_expr; + } + using exprns_::expr; + using exprns_::basic_expr; + using exprns_::extends; + using exprns_::is_breed_expr; + + template + struct or_; + + template + struct and_; + + template + struct not_; + + template< + typename Condition, + typename Then = sprout::breed::_, + typename Else = sprout::breed::not_ + > + struct if_; + + template()> + struct switch_; + + template + struct exact; + + template + struct convertible_to; + + template + struct vararg; + + SPROUT_STATIC_CONSTEXPR int N = (INT_MAX >> 10); + + namespace context { + struct null_context; + + template + struct null_eval; + + struct default_context; + + template< + typename Expr, + typename Context, + typename Tag = typename Expr::breed_tag, + long Arity = Expr::breed_arity_c + > + struct default_eval; + + template + struct callable_context; + + template + struct callable_eval; + } // namespace context + + using context::null_context; + using context::null_eval; + using context::default_context; + using context::default_eval; + using context::callable_context; + using context::callable_eval; + + namespace utility { + template + struct literal; + } // namespace context + + using utility::literal; + + namespace result_of { + template + struct as_expr; + + template + struct as_child; + + template > + struct child; + + template + struct child_c; + + template + struct left; + + template + struct right; + + template + struct deep_copy; + + template + struct eval; + + template< + typename Tag, + typename DomainOrArg, + typename... Args + > + struct make_expr; + + template + struct unpack_expr; + } // namespace result_of + + template + struct is_expr; + + template + struct is_domain; + + template + struct is_sub_domain_of; + + template + struct arity_of; + + template + struct domain_of; + + template + struct matches; + + template + struct unary_expr; + + template + struct binary_expr; + + template + struct nary_expr; + + template + struct terminal; + template + struct unary_plus; + template + struct negate; + template + struct dereference; + template + struct complement; + template + struct address_of; + template + struct logical_not; + template + struct pre_inc; + template + struct pre_dec; + template + struct post_inc; + template + struct post_dec; + + template + struct shift_left; + template + struct shift_right; + template + struct multiplies; + template + struct divides; + template + struct modulus; + template + struct plus; + template + struct minus; + template + struct less; + template + struct greater; + template + struct less_equal; + template + struct greater_equal; + template + struct equal_to; + template + struct not_equal_to; + template + struct logical_or; + template + struct logical_and; + template + struct bitwise_and; + template + struct bitwise_or; + template + struct bitwise_xor; + template + struct comma; + template + struct mem_ptr; + + template + struct assign; + template + struct shift_left_assign; + template + struct shift_right_assign; + template + struct multiplies_assign; + template + struct divides_assign; + template + struct modulus_assign; + template + struct plus_assign; + template + struct minus_assign; + template + struct bitwise_and_assign; + template + struct bitwise_or_assign; + template + struct bitwise_xor_assign; + template + struct subscript; + template + struct member; + template + struct if_else_; + + template + struct function; + + namespace functional { + struct left; + struct right; + struct eval; + struct deep_copy; + + template + struct as_expr; + + template + struct as_child; + + template > + struct child; + + template + struct child_c; + + template + struct make_expr; + + template + struct unpack_expr; + + typedef sprout::breed::functional::make_expr make_terminal; + typedef sprout::breed::functional::make_expr make_unary_plus; + typedef sprout::breed::functional::make_expr make_negate; + typedef sprout::breed::functional::make_expr make_dereference; + typedef sprout::breed::functional::make_expr make_complement; + typedef sprout::breed::functional::make_expr make_address_of; + typedef sprout::breed::functional::make_expr make_logical_not; + typedef sprout::breed::functional::make_expr make_pre_inc; + typedef sprout::breed::functional::make_expr make_pre_dec; + typedef sprout::breed::functional::make_expr make_post_inc; + typedef sprout::breed::functional::make_expr make_post_dec; + typedef sprout::breed::functional::make_expr make_shift_left; + typedef sprout::breed::functional::make_expr make_shift_right; + typedef sprout::breed::functional::make_expr make_multiplies; + typedef sprout::breed::functional::make_expr make_divides; + typedef sprout::breed::functional::make_expr make_modulus; + typedef sprout::breed::functional::make_expr make_plus; + typedef sprout::breed::functional::make_expr make_minus; + typedef sprout::breed::functional::make_expr make_less; + typedef sprout::breed::functional::make_expr make_greater; + typedef sprout::breed::functional::make_expr make_less_equal; + typedef sprout::breed::functional::make_expr make_greater_equal; + typedef sprout::breed::functional::make_expr make_equal_to; + typedef sprout::breed::functional::make_expr make_not_equal_to; + typedef sprout::breed::functional::make_expr make_logical_or; + typedef sprout::breed::functional::make_expr make_logical_and; + typedef sprout::breed::functional::make_expr make_bitwise_and; + typedef sprout::breed::functional::make_expr make_bitwise_or; + typedef sprout::breed::functional::make_expr make_bitwise_xor; + typedef sprout::breed::functional::make_expr make_comma; + typedef sprout::breed::functional::make_expr make_mem_ptr; + typedef sprout::breed::functional::make_expr make_assign; + typedef sprout::breed::functional::make_expr make_shift_left_assign; + typedef sprout::breed::functional::make_expr make_shift_right_assign; + typedef sprout::breed::functional::make_expr make_multiplies_assign; + typedef sprout::breed::functional::make_expr make_divides_assign; + typedef sprout::breed::functional::make_expr make_modulus_assign; + typedef sprout::breed::functional::make_expr make_plus_assign; + typedef sprout::breed::functional::make_expr make_minus_assign; + typedef sprout::breed::functional::make_expr make_bitwise_and_assign; + typedef sprout::breed::functional::make_expr make_bitwise_or_assign; + typedef sprout::breed::functional::make_expr make_bitwise_xor_assign; + typedef sprout::breed::functional::make_expr make_subscript; + typedef sprout::breed::functional::make_expr make_if_else; + typedef sprout::breed::functional::make_expr make_function; + + struct flatten; + struct make_pair; + struct first; + struct second; + struct at; + struct pop_front; + struct push_front; + struct pop_back; + struct push_back; + struct reverse; + } // namespace functional + + typedef functional::flatten _flatten; + typedef functional::make_pair _make_pair; + typedef functional::first _first; + typedef functional::second _second; + typedef functional::pop_front _at; + typedef functional::pop_front _pop_front; + typedef functional::push_front _push_front; + typedef functional::pop_back _pop_back; + typedef functional::push_back _push_back; + typedef functional::reverse _reverse; + typedef functional::eval _eval; + struct _deep_copy; + + typedef sprout::breed::functional::make_expr _make_terminal; + typedef sprout::breed::functional::make_expr _make_unary_plus; + typedef sprout::breed::functional::make_expr _make_negate; + typedef sprout::breed::functional::make_expr _make_dereference; + typedef sprout::breed::functional::make_expr _make_complement; + typedef sprout::breed::functional::make_expr _make_address_of; + typedef sprout::breed::functional::make_expr _make_logical_not; + typedef sprout::breed::functional::make_expr _make_pre_inc; + typedef sprout::breed::functional::make_expr _make_pre_dec; + typedef sprout::breed::functional::make_expr _make_post_inc; + typedef sprout::breed::functional::make_expr _make_post_dec; + typedef sprout::breed::functional::make_expr _make_shift_left; + typedef sprout::breed::functional::make_expr _make_shift_right; + typedef sprout::breed::functional::make_expr _make_multiplies; + typedef sprout::breed::functional::make_expr _make_divides; + typedef sprout::breed::functional::make_expr _make_modulus; + typedef sprout::breed::functional::make_expr _make_plus; + typedef sprout::breed::functional::make_expr _make_minus; + typedef sprout::breed::functional::make_expr _make_less; + typedef sprout::breed::functional::make_expr _make_greater; + typedef sprout::breed::functional::make_expr _make_less_equal; + typedef sprout::breed::functional::make_expr _make_greater_equal; + typedef sprout::breed::functional::make_expr _make_equal_to; + typedef sprout::breed::functional::make_expr _make_not_equal_to; + typedef sprout::breed::functional::make_expr _make_logical_or; + typedef sprout::breed::functional::make_expr _make_logical_and; + typedef sprout::breed::functional::make_expr _make_bitwise_and; + typedef sprout::breed::functional::make_expr _make_bitwise_or; + typedef sprout::breed::functional::make_expr _make_bitwise_xor; + typedef sprout::breed::functional::make_expr _make_comma; + typedef sprout::breed::functional::make_expr _make_mem_ptr; + typedef sprout::breed::functional::make_expr _make_assign; + typedef sprout::breed::functional::make_expr _make_shift_left_assign; + typedef sprout::breed::functional::make_expr _make_shift_right_assign; + typedef sprout::breed::functional::make_expr _make_multiplies_assign; + typedef sprout::breed::functional::make_expr _make_divides_assign; + typedef sprout::breed::functional::make_expr _make_modulus_assign; + typedef sprout::breed::functional::make_expr _make_plus_assign; + typedef sprout::breed::functional::make_expr _make_minus_assign; + typedef sprout::breed::functional::make_expr _make_bitwise_and_assign; + typedef sprout::breed::functional::make_expr _make_bitwise_or_assign; + typedef sprout::breed::functional::make_expr _make_bitwise_xor_assign; + typedef sprout::breed::functional::make_expr _make_subscript; + typedef sprout::breed::functional::make_expr _make_if_else; + typedef sprout::breed::functional::make_expr _make_function; + + template + struct is_callable; + + template + struct is_transform; + + template + struct is_aggregate; + +# define SPROUT_BREED_UNEXPR() typedef int breed_is_expr_; +# define SPROUT_BREED_CALLABLE() typedef void breed_is_callable_; +# define SPROUT_BREED_AGGREGATE() typedef void breed_is_aggregate_; +# define SPROUT_BREED_USE_BASIC_EXPR() typedef void breed_use_basic_expr_; + + struct callable { + public: + SPROUT_BREED_CALLABLE(); + }; + + struct external_transform; + + template + struct transform; + + template + struct when; + + template + struct otherwise; + + template + struct call; + + template + struct make; + + template + struct protect; + + template + struct noinvoke; + + template + struct lazy; + + template + struct fold; + + template + struct reverse_fold; + + template + struct fold_tree; + + template + struct reverse_fold_tree; + + template + struct pass_through; + + template + struct _default; + + struct _expr; + struct _state; + struct _data; + + struct _value; + + struct _void; + + template + struct integral_c; + + template + struct char_; + + template + struct int_; + + template + struct long_; + + template + struct size_t; + + template + struct _child_c; + + typedef _child_c<0> _child0; + typedef _child_c<1> _child1; + typedef _child0 _child; + typedef _child0 _left; + typedef _child1 _right; + + typedef _child_c<2> _child2; + + struct _byref; + struct _byval; + + template + struct is_extension; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_BREED_FWD_HPP diff --git a/sprout/breed/core.hpp b/sprout/breed/core.hpp new file mode 100644 index 00000000..f211788c --- /dev/null +++ b/sprout/breed/core.hpp @@ -0,0 +1,19 @@ +#ifndef SPROUT_BREED_CORE_HPP +#define SPROUT_BREED_CORE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +//#include +//#include +//#include + +#endif // #ifndef SPROUT_BREED_CORE_HPP diff --git a/sprout/breed/detail/as_expr.hpp b/sprout/breed/detail/as_expr.hpp new file mode 100644 index 00000000..cadf7e0f --- /dev/null +++ b/sprout/breed/detail/as_expr.hpp @@ -0,0 +1,148 @@ +#ifndef SPROUT_BREED_DETAIL_AS_EXPR_HPP +#define SPROUT_BREED_DETAIL_AS_EXPR_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template + struct base_generator { + public: + typedef Generator type; + }; + template + struct base_generator > { + public: + typedef Generator type; + }; + + template + struct as_expr; + template + struct as_expr { + public: + typedef typename sprout::breed::detail::term_traits::value_type value_type; + typedef sprout::breed::expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > expr_type; + typedef typename Generator::template result::type result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return Generator()(expr_type::make(t)); + } + }; + template + struct as_expr { + public: + typedef typename sprout::breed::detail::term_traits::value_type value_type; + typedef sprout::breed::basic_expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > expr_type; + typedef typename Generator::template result::type result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return Generator()(expr_type::make(t)); + } + }; + template + struct as_expr { + public: + typedef typename sprout::breed::detail::term_traits::value_type value_type; + typedef sprout::breed::expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return result_type::make(t); + } + }; + template + struct as_expr { + public: + typedef typename sprout::breed::detail::term_traits::value_type value_type; + typedef sprout::breed::basic_expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return result_type::make(t); + } + }; + + template + struct as_child; + template + struct as_child { + public: + typedef T const& reference; + typedef sprout::breed::expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > expr_type; + typedef typename Generator::template result::type result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return Generator()(expr_type::make(t)); + } + }; + template + struct as_child { + public: + typedef T const& reference; + typedef sprout::breed::basic_expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > expr_type; + typedef typename Generator::template result::type result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return Generator()(expr_type::make(t)); + } + }; + template + struct as_child { + public: + typedef T const& reference; + typedef sprout::breed::expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return result_type::make(t); + } + }; + template + struct as_child { + public: + typedef T const& reference; + typedef sprout::breed::basic_expr< + sprout::breed::tag::terminal, + sprout::breed::term, + 0 + > result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& t) const { + return result_type::make(t); + } + }; + } // namespace detail + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_DETAIL_AS_EXPR_HPP diff --git a/sprout/breed/detail/deduce_domain.hpp b/sprout/breed/detail/deduce_domain.hpp new file mode 100644 index 00000000..3ad3ebff --- /dev/null +++ b/sprout/breed/detail/deduce_domain.hpp @@ -0,0 +1,226 @@ +#ifndef SPROUT_BREED_DETAIL_DEDUCE_DOMAIN_HPP +#define SPROUT_BREED_DETAIL_DEDUCE_DOMAIN_HPP + +#include +#include +#include +#include +#include + +// +// SPROUT_BREED_ASSERT_VALID_DOMAIN +// +#ifndef SPROUT_BREED_ASSERT_VALID_DOMAIN +# define SPROUT_BREED_ASSERT_VALID_DOMAIN(DOM) static_assert( \ + !std::is_same::value, \ + "!std::is_same::value" \ + ) +#endif + +namespace sprout { + namespace breed { + namespace detail { + template + struct domain_ + : public domain_ + { + public: + typedef Domain type; + typedef domain_ base; + public: + using base::deduce_; + static SPROUT_CONSTEXPR type deduce_(domain_ const*); + }; + template<> + struct domain_ { + public: + typedef sprout::breed::detail::not_a_domain type; + public: + static type deduce_(void const*); + }; + + template<> + struct domain_ + : public domain_ + {}; + + template<> + struct domain_ + : public domain_ + {}; + + sprout::breed::detail::sized_type<1>::type default_test( + void const*, + void const* + ); + sprout::breed::detail::sized_type<2>::type default_test( + sprout::breed::detail::domain_ const*, + void const* + ); + sprout::breed::detail::sized_type<2>::type default_test( + sprout::breed::detail::domain_ const*, void const* + ); + sprout::breed::detail::sized_type<3>::type default_test( + void const*, + sprout::breed::detail::domain_ const* + ); + sprout::breed::detail::sized_type<3>::type default_test( + void const*, + sprout::breed::detail::domain_ const* + ); + sprout::breed::detail::sized_type<4>::type default_test( + sprout::breed::detail::domain_ const*, + sprout::breed::detail::domain_ const* + ); + sprout::breed::detail::sized_type<4>::type default_test( + sprout::breed::detail::domain_ const*, + sprout::breed::detail::domain_ const* + ); + sprout::breed::detail::sized_type<4>::type default_test( + sprout::breed::detail::domain_ const*, + sprout::breed::detail::domain_ const* + ); + sprout::breed::detail::sized_type<4>::type default_test( + sprout::breed::detail::domain_ const*, + sprout::breed::detail::domain_ const* + ); + + template + struct common_domain1 { + public: + typedef D0 type; + }; + + template + struct deduce_domain1 + : public sprout::breed::domain_of + {}; + + template< + typename D0, + typename D1, + int DefaultCase = sizeof( + sprout::breed::detail::default_test( + static_cast const*>(0), + static_cast const*>(0) + ) + ) + > + struct common_domain2 { + public: + typedef decltype(sprout::breed::detail::domain_::deduce_( + static_cast const*>(0) + )) type; + }; + template + struct common_domain2 { + public: + typedef D1 type; + }; + template + struct common_domain2 { + public: + typedef D0 type; + }; + template + struct common_domain2 { + public: + typedef D0 type; + }; + template + struct common_domain2 { + public: + typedef D0 type; + }; + template + struct common_domain2 { + public: + typedef D1 type; + }; + template + struct common_domain2 { + public: + typedef D1 type; + }; + template<> + struct common_domain2 { + public: + typedef sprout::breed::default_domain type; + }; + template<> + struct common_domain2 { + public: + typedef sprout::breed::default_domain type; + }; + template<> + struct common_domain2 { + public: + typedef sprout::breed::default_domain type; + }; + template<> + struct common_domain2 { + public: + typedef sprout::breed::basic_default_domain type; + }; + + template + struct deduce_domain2 + : public common_domain2< + typename sprout::breed::domain_of::type, + typename sprout::breed::domain_of::type + > + {}; + + template + struct common_domain { + private: + template + struct common_impl { + public: + typedef typename common_impl< + typename sprout::breed::detail::common_domain2::type, + Tail... + >::type type; + }; + template + struct common_impl { + public: + typedef typename sprout::breed::detail::common_domain2::type type; + }; + public: + template + struct common + : public common_impl + {}; + template + struct common + : public sprout::breed::detail::common_domain1 + {}; + public: + typedef typename common::type type; + SPROUT_BREED_ASSERT_VALID_DOMAIN(type); + }; + + template + struct deduce_domain_impl; + template + struct deduce_domain_impl, Args...> + : public sprout::breed::detail::common_domain< + typename sprout::breed::domain_of< + typename sprout::tppack_at::type + >::type... + > + {}; + + template + struct deduce_domain + : public sprout::breed::detail::deduce_domain_impl< + typename sprout::index_range<0, sizeof...(Args)>::type, + Args... + > + {}; + } // namespace detail + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_DETAIL_DEDUCE_DOMAIN_HPP diff --git a/sprout/breed/detail/std_result_of.hpp b/sprout/breed/detail/std_result_of.hpp new file mode 100644 index 00000000..7a2bde6a --- /dev/null +++ b/sprout/breed/detail/std_result_of.hpp @@ -0,0 +1,18 @@ +#ifndef SPROUT_BREED_DETAIL_STD_RESULT_OF_HPP +#define SPROUT_BREED_DETAIL_STD_RESULT_OF_HPP + +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template + struct std_result_of + : public std::result_of + {}; + } // namespace detail + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_DETAIL_STD_RESULT_OF_HPP diff --git a/sprout/breed/detail/template_arity.hpp b/sprout/breed/detail/template_arity.hpp new file mode 100644 index 00000000..7b9cf77d --- /dev/null +++ b/sprout/breed/detail/template_arity.hpp @@ -0,0 +1,25 @@ +#ifndef SPROUT_BREED_DETAIL_TEMPLATE_ARITY_HPP +#define SPROUT_BREED_DETAIL_TEMPLATE_ARITY_HPP + +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template + struct template_arity_impl; + template class F, typename... Args> + struct template_arity_impl > + : public std::integral_constant + {}; + + template + struct template_arity + : public sprout::breed::detail::template_arity_impl + {}; + } // namespace detail + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_DETAIL_TEMPLATE_ARITY_HPP diff --git a/sprout/breed/domain.hpp b/sprout/breed/domain.hpp new file mode 100644 index 00000000..a37fc246 --- /dev/null +++ b/sprout/breed/domain.hpp @@ -0,0 +1,183 @@ +#ifndef SPROUT_BREED_DOMAIN_HPP +#define SPROUT_BREED_DOMAIN_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + struct not_a_generator {}; + struct not_a_grammar {}; + struct not_a_domain {}; + } // namespace detail + + namespace domainns_ { + // + // domain + // + template< + typename Generator, + typename Grammar, + typename Super + > + struct domain + : public Generator + { + public: + typedef Generator breed_generator; + typedef Grammar breed_grammar; + typedef Super breed_super_domain; + typedef domain breed_base_domain; + typedef void breed_is_domain_; + public: + template + struct as_expr + : public detail::as_expr< + T, + typename sprout::breed::detail::base_generator::type, + sprout::breed::wants_basic_expr::value + > + { + public: + SPROUT_BREED_CALLABLE() + }; + template + struct as_expr { + public: + SPROUT_BREED_CALLABLE() + public: + typedef typename std::remove_const::type result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& e) const { + return e; + } + }; + template + struct as_child + : public detail::as_child< + T, + typename sprout::breed::detail::base_generator::type, + sprout::breed::wants_basic_expr::value + > + { + public: + SPROUT_BREED_CALLABLE() + }; + template + struct as_child { + public: + SPROUT_BREED_CALLABLE() + public: + typedef T &result_type; + public: + SPROUT_CONSTEXPR result_type operator()(T const& e) const { + return e; + } + }; + }; + + // + // default_domain + // + struct default_domain + : public sprout::breed::domain<> + {}; + + // + // basic_default_domain + // + struct basic_default_domain + : public sprout::breed::domain + {}; + + // + // deduce_domain + // + struct deduce_domain + : public sprout::breed::domain< + sprout::breed::detail::not_a_generator, + sprout::breed::detail::not_a_grammar, + sprout::breed::detail::not_a_domain + > + {}; + + // + // base_expr + // + template + struct base_expr { + public: + typedef sprout::breed::expr type; + }; + template + struct base_expr { + public: + typedef sprout::breed::basic_expr type; + }; + } // namespace domainns_ + + // + // is_domain + // + template + struct is_domain + : public std::false_type + {}; + template + struct is_domain + : public std::true_type + {}; + + // + // domain_of + // + template + struct domain_of { + public: + typedef sprout::breed::default_domain type; + }; + template + struct domain_of { + public: + typedef typename T::breed_domain type; + }; + template + struct domain_of { + public: + typedef typename sprout::breed::domain_of::type type; + }; + template + struct domain_of, void> { + public: + typedef typename sprout::breed::domain_of::type type; + }; + template + struct domain_of const, void> { + typedef typename sprout::breed::domain_of::type type; + }; + + // + // is_sub_domain_of + // + template + struct is_sub_domain_of + : public is_sub_domain_of + {}; + template + struct is_sub_domain_of + : public std::false_type + {}; + template + struct is_sub_domain_of + : public std::true_type + {}; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_DOMAIN_HPP diff --git a/sprout/breed/eval.hpp b/sprout/breed/eval.hpp new file mode 100644 index 00000000..baae2d67 --- /dev/null +++ b/sprout/breed/eval.hpp @@ -0,0 +1,87 @@ +#ifndef SPROUT_BREED_EVAL_HPP +#define SPROUT_BREED_EVAL_HPP + +#include +#include +#include + +namespace sprout { + namespace breed { + namespace result_of { + // + // eval + // + template + struct eval { + public: + typedef typename Context::template eval::result_type type; + }; + } // namespace result_of + + namespace functional { + // + // eval + // + struct eval { + public: + SPROUT_BREED_CALLABLE(); + public: + template + struct result; + template + struct result { + typedef typename sprout::breed::result_of::eval< + typename std::remove_reference::type, + typename std::remove_reference::type + >::type type; + }; + template + typename sprout::breed::result_of::eval::type + operator()(Expr& e, Context& ctx) const { + return typename Context::template eval()(e, ctx); + } + template + typename sprout::breed::result_of::eval::type + operator()(Expr& e, Context const& ctx) const { + return typename Context::template eval()(e, ctx); + } + template + typename sprout::breed::result_of::eval::type + operator()(Expr const& e, Context& ctx) const { + return typename Context::template eval()(e, ctx); + } + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::eval::type + operator()(Expr const& e, Context const& ctx) const { + return typename Context::template eval()(e, ctx); + } + }; + } // namespace functional + + // + // eval + // + template + typename sprout::breed::result_of::eval::type + eval(Expr& e, Context& ctx) { + return typename Context::template eval()(e, ctx); + } + template + typename sprout::breed::result_of::eval::type + eval(Expr& e, Context const& ctx) { + return typename Context::template eval()(e, ctx); + } + template + typename sprout::breed::result_of::eval::type + eval(Expr const& e, Context& ctx) { + return typename Context::template eval()(e, ctx); + } + template + typename sprout::breed::result_of::eval::type + SPROUT_CONSTEXPR eval(Expr const& e, Context const& ctx) { + return typename Context::template eval()(e, ctx); + } + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_EVAL_HPP diff --git a/sprout/breed/expr.hpp b/sprout/breed/expr.hpp new file mode 100644 index 00000000..bc16a627 --- /dev/null +++ b/sprout/breed/expr.hpp @@ -0,0 +1,477 @@ +#ifndef SPROUT_BREED_EXPR_HPP +#define SPROUT_BREED_EXPR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + struct not_a_valid_type { + private: + SPROUT_CONSTEXPR not_a_valid_type() {} + }; + + template + struct address_of_hack { + public: + typedef sprout::breed::detail::not_a_valid_type type; + }; + template + struct address_of_hack { + typedef Expr* type; + }; + + template + SPROUT_CONSTEXPR Expr make_terminal(T const& t, Expr*, sprout::breed::term const*) { + return Expr(t); + } + template + SPROUT_CONSTEXPR Expr make_terminal(T const (&t)[N], Expr const*, sprout::breed::term const*) { + return throw "Sorry, not implemented.", Expr(); + } + + template + struct same_cv { + public: + typedef U type; + }; + template + struct same_cv { + public: + typedef U const type; + }; + } // namespace detail + + namespace result_of { + namespace detail { + template + struct funop_impl { + public: + typedef typename sprout::breed::base_expr< + Domain, + sprout::breed::tag::function, + sprout::breed::list< + Expr const&, + typename sprout::breed::result_of::as_child::type... + > + >::type type; + public: + static SPROUT_CONSTEXPR type const call( + Expr const& e, + Args const&... args + ) const + { + return type( + e, + sprout::breed::as_child(args)... + ); + } + }; + } // namespace detail + // + // funop + // + template + struct funop; + template + struct funop + : public sprout::breed::result_of::detail::funop_impl< + typename sprout::breed::detail::same_cv::type, + Domain, + typename std::remove_reference::type... + > + {}; + } // namespace result_of + + namespace exprns_ { + // + // basic_expr + // + template + struct basic_expr, 0> { + public: + SPROUT_STATIC_CONSTEXPR long breed_arity_c = 0; + public: + typedef Tag breed_tag; + typedef std::integral_constant breed_arity; + typedef basic_expr breed_base_expr; + typedef sprout::breed::term breed_args; + typedef basic_expr breed_grammar; + typedef sprout::breed::basic_default_domain breed_domain; + typedef sprout::breed::default_generator breed_generator; + typedef sprout::breed::tag::breed_expr fusion_tag; + typedef basic_expr breed_derived_expr; + typedef void breed_is_expr_; + typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + public: + template + static SPROUT_CONSTEXPR basic_expr make(A const& arg) { + return sprout::breed::detail::make_terminal( + arg, + static_cast(0), + static_cast(0) + ); + } + private: + sprout::tuples::tuple children_; + public: + SPROUT_CONSTEXPR explicit basic_expr(Arg const& arg) + : children_(arg) + {} + template + SPROUT_CONSTEXPR typename breed_child::type const& child() const { + return sprout::tuples::get(children_); + } + template + typename breed_child::type const& child() { + return sprout::tuples::get(children_); + } + SPROUT_CONSTEXPR basic_expr const& breed_base() const { + return *this; + } + basic_expr& breed_base() { + return *this; + } + }; + template + struct basic_expr, sizeof...(Args)> { + public: + SPROUT_STATIC_CONSTEXPR long breed_arity_c = sizeof...(Args); + public: + typedef Tag breed_tag; + typedef std::integral_constant breed_arity; + typedef basic_expr breed_base_expr; + typedef sprout::breed::list breed_args; + typedef basic_expr breed_grammar; + typedef sprout::breed::basic_default_domain breed_domain; + typedef sprout::breed::default_generator breed_generator; + typedef sprout::breed::tag::breed_expr fusion_tag; + typedef basic_expr breed_derived_expr; + typedef void breed_is_expr_; + typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + public: + template + static SPROUT_CONSTEXPR basic_expr make(As const&... args) { + return basic_expr(args...); + } + private: + sprout::tuples::tuple children_; + public: + SPROUT_CONSTEXPR explicit basic_expr(Args const&... args) + : children_(args...) + {} + template + SPROUT_CONSTEXPR typename breed_child::type const& child() const { + return sprout::tuples::get(children_); + } + template + typename breed_child::type const& child() { + return sprout::tuples::get(children_); + } + SPROUT_CONSTEXPR basic_expr const& breed_base() const { + return *this; + } + basic_expr& breed_base() { + return *this; + } + }; + + // + // expr + // + template + struct expr, 0> { + public: + SPROUT_STATIC_CONSTEXPR long breed_arity_c = 0; + public: + typedef Tag breed_tag; + typedef std::integral_constant breed_arity; + typedef expr breed_base_expr; + typedef sprout::breed::term breed_args; + typedef basic_expr breed_grammar; + typedef sprout::breed::basic_default_domain breed_domain; + typedef sprout::breed::default_generator breed_generator; + typedef sprout::breed::tag::breed_expr fusion_tag; + typedef expr breed_derived_expr; + typedef void proto_is_expr_; + typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + template + struct result { + public: + typedef typename sprout::breed::result_of::funop< + Sig, + expr, + sprout::breed::default_domain + >::type type; + }; + public: + template + static SPROUT_CONSTEXPR expr make(A const& arg) { + return sprout::breed::detail::make_terminal( + arg, + static_cast(0), + static_cast(0) + ); + } + private: + sprout::tuples::tuple children_; + public: + SPROUT_CONSTEXPR explicit expr(Arg const& arg) + : children_(arg) + {} + template + SPROUT_CONSTEXPR typename breed_child::type const& child() const { + return sprout::tuples::get(children_); + } + template + typename breed_child::type const& child() { + return sprout::tuples::get(children_); + } + SPROUT_CONSTEXPR expr const& breed_base() const { + return *this; + } + expr& breed_base() { + return *this; + } + SPROUT_CONSTEXPR sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list, + 2 + > operator=(expr const& arg) const { + return sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list, + 2 + >(*this, arg); + } + template + SPROUT_CONSTEXPR sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + > operator=(A const& arg) const { + return sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + > operator=(A& arg) const { + return sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + SPROUT_CONSTEXPR sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + > operator[](A const& arg) const { + return sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + > operator[](A& arg) const { + return sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::funop< + expr(As const&...), + expr, + sprout::breed::default_domain + >::type operator()(As const&... args) const { + return sprout::breed::result_of::funop< + expr(As const&...), + expr, + sprout::breed::default_domain + >::call(*this, args...); + } + }; + template + struct expr, sizeof...(Args)> { + public: + SPROUT_STATIC_CONSTEXPR long breed_arity_c = sizeof...(Args); + public: + typedef Tag breed_tag; + typedef std::integral_constant breed_arity; + typedef expr breed_base_expr; + typedef sprout::breed::list breed_args; + typedef basic_expr breed_grammar; + typedef sprout::breed::basic_default_domain breed_domain; + typedef sprout::breed::default_generator breed_generator; + typedef sprout::breed::tag::breed_expr fusion_tag; + typedef expr breed_derived_expr; + typedef void proto_is_expr_; + typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + template + struct result { + public: + typedef typename sprout::breed::result_of::funop< + Sig, + expr, + sprout::breed::default_domain + >::type type; + }; + public: + template + static SPROUT_CONSTEXPR basic_expr make(As const&... args) { + return basic_expr(args...); + } + private: + sprout::tuples::tuple children_; + public: + SPROUT_CONSTEXPR explicit basic_expr(Args const&... args) + : children_(args...) + {} + template + SPROUT_CONSTEXPR typename breed_child::type const& child() const { + return sprout::tuples::get(children_); + } + template + typename breed_child::type const& child() { + return sprout::tuples::get(children_); + } + SPROUT_CONSTEXPR basic_expr const& breed_base() const { + return *this; + } + basic_expr& breed_base() { + return *this; + } + SPROUT_CONSTEXPR sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list, + 2 + > operator=(expr const& arg) const { + return sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list, + 2 + >(*this, arg); + } + template + SPROUT_CONSTEXPR sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + > operator=(A const& arg) const { + return sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + > operator=(A& arg) const { + return sprout::breed::expr< + sprout::breed::tag::assign, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + SPROUT_CONSTEXPR sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + > operator[](A const& arg) const { + return sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + > operator[](A& arg) const { + return sprout::breed::expr< + sprout::breed::tag::subscript, + sprout::breed::list::type>, + 2 + >(*this, sprout::breed::as_child(arg)); + } + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::funop< + expr(As const&...), + expr, + sprout::breed::default_domain + >::type operator()(As const&... args) const { + return sprout::breed::result_of::funop< + expr(As const&...), + expr, + sprout::breed::default_domain + >::call(*this, args...); + } + }; + } // namespace exprns_ + + // + // unexpr + // + template + struct unexpr + : public Expr + { + public: + SPROUT_BREED_UNEXPR(); + public: + SPROUT_CONSTEXPR explicit unexpr(Expr const& e) + : Expr(e) + {} + using Expr::operator=; + }; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_EXPR_HPP diff --git a/sprout/breed/generate.hpp b/sprout/breed/generate.hpp new file mode 100644 index 00000000..aadbc95a --- /dev/null +++ b/sprout/breed/generate.hpp @@ -0,0 +1,322 @@ +#ifndef SPROUT_BREED_GENERATE_HPP +#define SPROUT_BREED_GENERATE_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template + struct by_value_generator_; + template + struct by_value_generator_, 0> > { + public: + typedef breed::expr< + Tag, + sprout::breed::term::value_type>, + 0 + > type; + public: + static SPROUT_CONSTEXPR type call(breed::expr, 0> const& e) { + return type(e.template child<0>()); + } + }; + template + struct by_value_generator_, 0> > { + public: + typedef breed::expr< + Tag, + sprout::breed::term::value_type>, + 0 + > type; + public: + static SPROUT_CONSTEXPR type call(breed::expr, 0> const& e) { + return type(e.template child<0>()); + } + }; + template + struct by_value_generator_< + sprout::breed::expr, sizeof...(Args)> + > { + public: + typedef sprout::breed::list src_args; + typedef sprout::breed::list::type...> dst_args; + typedef sprout::breed::expr src_type; + typedef sprout::breed::expr type; + private: + template + static SPROUT_CONSTEXPR type call_impl(src_type const& e, sprout::index_tuple) { + return type(e.template child()...); + } + public: + static SPROUT_CONSTEXPR type call(src_type const& e) { + return call_impl(typename sprout::index_range<0, sizeof...(Args)>::type()); + } + }; + template + struct by_value_generator_< + sprout::breed::basic_expr, sizeof...(Args)> + > { + public: + typedef sprout::breed::list src_args; + typedef sprout::breed::list::type...> dst_args; + typedef sprout::breed::basic_expr src_type; + typedef sprout::breed::basic_expr type; + private: + template + static SPROUT_CONSTEXPR type call_impl(src_type const& e, sprout::index_tuple) { + return type(e.template child()...); + } + public: + static SPROUT_CONSTEXPR type call(src_type const& e) { + return call_impl(typename sprout::index_range<0, sizeof...(Args)>::type()); + } + }; + } // namespace detail + + // + // use_basic_expr + // + template + struct use_basic_expr + : public Generator + { + public: + SPROUT_BREED_USE_BASIC_EXPR(); + }; + + // + // default_generator + // + struct default_generator { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef Expr type; + }; + public: + template +#ifdef SPROUT_BREED_STRICT_RESULT_OF + SPROUT_CONSTEXPR Expr +#else + SPROUT_CONSTEXPR Expr const& +#endif + operator()(Expr const& e) const { + return e; + } + }; + + // + // basic_default_generator + // + struct basic_default_generator + : public sprout::breed::use_basic_expr + {}; + + // + // generator + // + template class Extends> + struct generator { + SPROUT_BREED_CALLABLE() + SPROUT_BREED_USE_BASIC_EXPR() + public: + template + struct result; + template + struct result { + public: + typedef Extends type; + }; + template + struct result { + public: + typedef Extends type; + }; + template + struct result + { + public: + typedef Extends type; + }; + public: + template + SPROUT_CONSTEXPR Extends operator()(Expr const& e) const { + return Extends(e); + } + }; + + // + // pod_generator + // + template class Extends> + struct pod_generator { + public: + SPROUT_BREED_CALLABLE() + SPROUT_BREED_USE_BASIC_EXPR() + public: + template + struct result; + template + struct result { + public: + typedef Extends type; + }; + template + struct result { + public: + typedef Extends type; + }; + template + struct result { + public: + typedef Extends type; + }; + public: + template + SPROUT_CONSTEXPR Extends operator()(Expr const& e) const { + return Extends(e); + } + }; + + // + // by_value_generator + // + struct by_value_generator { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename sprout::breed::detail::by_value_generator_::type type; + }; + template + struct result { + public: + typedef typename sprout::breed::detail::by_value_generator_::type type; + }; + template + struct result { + public: + typedef typename sprout::breed::detail::by_value_generator_::type type; + }; + public: + template + SPROUT_CONSTEXPR typename result::type operator()(Expr const& e) const { + return sprout::breed::detail::by_value_generator_::call(e); + } + }; + + // + // compose_generators + // + template + struct compose_generators { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename Second::template result< + Second(typename First::template result::type) + >::type type; + }; + template + struct result { + public: + typedef typename Second::template result< + Second(typename First::template result::type) + >::type type; + }; + template + struct result { + public: + typedef typename Second::template result< + Second(typename First::template result::type) + >::type type; + }; + public: + template + SPROUT_CONSTEXPR typename result::type operator()(Expr const& e) const { + return Second()(First()(e)); + } + }; + + // + // wants_basic_expr + // + template + struct wants_basic_expr + : public std::false_type + {}; + template + struct wants_basic_expr + : public std::true_type + {}; + + // + // is_callable + // + template<> + struct is_callable + : public std::true_type + {}; + template class Extends> + struct is_callable > + : public std::true_type + {}; + template class Extends> + struct is_callable > + : public std::true_type + {}; + template<> + struct is_callable + : public std::true_type + {}; + template + struct is_callable > + : public std::true_type + {}; + + namespace detail { + template + struct std_result_of { + public: + typedef Expr type; + }; + template + struct std_result_of { + public: + typedef Expr type; + }; + template + struct std_result_of { + public: + typedef Expr type; + }; + template + struct std_result_of { + public: + typedef Expr type; + }; + } // namespace detail + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_GENERATE_HPP diff --git a/sprout/breed/matches.hpp b/sprout/breed/matches.hpp new file mode 100644 index 00000000..cdca04fe --- /dev/null +++ b/sprout/breed/matches.hpp @@ -0,0 +1,16 @@ +#ifndef SPROUT_BREED_MATCHES_HPP +#define SPROUT_BREED_MATCHES_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_MATCHES_HPP diff --git a/sprout/breed/tags.hpp b/sprout/breed/tags.hpp new file mode 100644 index 00000000..f5c6a4e6 --- /dev/null +++ b/sprout/breed/tags.hpp @@ -0,0 +1,62 @@ +#ifndef SPROUT_BREED_TAGS_HPP +#define SPROUT_BREED_TAGS_HPP + +#include +#include + +namespace sprout { + namespace breed { + namespace tagns_ { + namespace tag { + struct terminal {}; + struct unary_plus {}; + struct negate {}; + struct dereference {}; + struct complement {}; + struct address_of {}; + struct logical_not {}; + struct pre_inc {}; + struct pre_dec {}; + struct post_inc {}; + struct post_dec {}; + struct shift_left {}; + struct shift_right {}; + struct multiplies {}; + struct divides {}; + struct modulus {}; + struct plus {}; + struct minus {}; + struct less {}; + struct greater {}; + struct less_equal {}; + struct greater_equal {}; + struct equal_to {}; + struct not_equal_to {}; + struct logical_or {}; + struct logical_and {}; + struct bitwise_and {}; + struct bitwise_or {}; + struct bitwise_xor {}; + struct comma {}; + struct mem_ptr {}; + struct assign {}; + struct shift_left_assign {}; + struct shift_right_assign {}; + struct multiplies_assign {}; + struct divides_assign {}; + struct modulus_assign {}; + struct plus_assign {}; + struct minus_assign {}; + struct bitwise_and_assign {}; + struct bitwise_or_assign {}; + struct bitwise_xor_assign {}; + struct subscript {}; + struct member {}; + struct if_else_ {}; + struct function {}; + } // namespace tag + } // namespace tagns_ + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_TAGS_HPP diff --git a/sprout/breed/traits.hpp b/sprout/breed/traits.hpp new file mode 100644 index 00000000..e6ceb9fc --- /dev/null +++ b/sprout/breed/traits.hpp @@ -0,0 +1,926 @@ +#ifndef SPROUT_BREED_TRAITS_HPP +#define SPROUT_BREED_TRAITS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template + struct if_vararg {}; + template + struct if_vararg + : public T + {}; + + template + struct is_callable2_ + : public std::false_type + {}; + template + struct is_callable2_ + : public std::true_type + {}; + template::value> + struct is_callable_ + : public sprout::breed::detail::is_callable2_ + {}; + } // namespace detail + // + // is_callable + // + template + struct is_callable + : public sprout::breed::detail::is_callable_ + {}; + template<> + struct is_callable + : public std::true_type + {}; + template<> + struct is_callable + : public std::false_type + {}; + template + struct is_callable > + : public std::false_type + {}; + + namespace detail { + template + struct is_transform_ + : public std::false_type + {}; + template + struct is_transform_ + : public std::true_type + {}; + } // namespace detail + // + // is_transform + // + template + struct is_transform + : public sprout::breed::detail::is_transform_ + {}; + + namespace detail { + template + struct is_aggregate_ + : public std::is_pod + {}; + template + struct is_aggregate_, void> + : public std::false_type + {}; + template + struct is_aggregate_, void> + : public std::false_type + {}; + template + struct is_aggregate_ + : public std::true_type + {}; + } // namespace detail + // + // is_transform + // + template + struct is_aggregate + : public sprout::breed::detail::is_aggregate_ + {}; + + // + // is_transform + // + template + struct is_expr + : public std::false_type + {}; + template + struct is_expr + : public std::true_type + {}; + template + struct is_expr + : public is_expr + {}; + + // + // tag_of + // + template + struct tag_of { + public: + typedef typename Expr::breed_tag type; + }; + template + struct tag_of { + public: + typedef typename Expr::breed_tag type; + }; + + // + // arity_of + // + template + struct arity_of + : public Expr::breed_arity + {}; + template + struct arity_of + : public Expr::breed_arity + {}; + + namespace result_of { + // + // as_expr + // + template + struct as_expr { + public: + typedef typename Domain::template as_expr::result_type type; + }; + + // + // as_child + // + template + struct as_child { + public: + typedef typename Domain::template as_child::result_type type; + }; + + // + // child + // + template + struct child + : public child_c + {}; + + // + // value + // + template + struct value { + static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c"); + public: + typedef typename Expr::template breed_child<0>::type value_type; + typedef typename sprout::breed::detail::term_traits::value_type type; + }; + template + struct value { + static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c"); + public: + typedef typename Expr:template breed_child<0>::type value_type; + typedef typename sprout::breed::detail::term_traits::reference type; + }; + template + struct value { + static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c"); + public: + typedef typename Expr:template breed_child<0>::type value_type; + typedef typename sprout::breed::detail::term_traits::const_reference type; + }; + + // + // left + // + template + struct left + : public sprout::breed::result_of::child_c + {}; + // + // right + // + template + struct right + : public child_c + {}; + } // namespace result_of + + // + // terminal + // + template + struct terminal + : public sprout::breed::transform, int> + { + public: + typedef sprout::breed::tag::terminal breed_tag; + typedef sprout::breed::expr, 0> type; + typedef sprout::breed::basic_expr, 0> breed_grammar; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + public: + template + struct impl + : public sprout::breed::transform_impl + { + public: + typedef Expr result_type; + public: +#ifdef SPROUT_BREED_STRICT_RESULT_OF + SPROUT_CONSTEXPR result_type +#else + SPROUT_CONSTEXPR typename impl::expr_param +#endif + operator()( + typename impl::expr_param e, + typename impl::state_param, + typename impl::data_param + ) const + { + return e; + } + }; + }; + + // + // if_else_ + // + template + struct if_else_ + : public sprout::breed::transform, int> + { + public: + typedef sprout::breed::tag::if_else_ breed_tag; + typedef sprout::breed::expr< + sprout::breed::tag::if_else_, sprout::breed::sprout::breed::list, + 3 + > type; + typedef sprout::breed::basic_expr< + sprout::breed::tag::if_else_, + sprout::breed::sprout::breed::list, + 3 + > breed_grammar; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + public: + template + struct impl + : public sprout::breed::detail::pass_through_impl + {}; + }; + + // + // nullary_expr + // + template + struct nullary_expr + : public sprout::breed::transform, int> + { + public: + typedef Tag breed_tag; + typedef sprout::breed::expr, 0> type; + typedef sprout::breed::basic_expr, 0> breed_grammar; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + public: + template + struct impl + : public sprout::breed::transform_impl + { + public: + typedef Expr result_type; + public: +#ifdef SPROUT_BREED_STRICT_RESULT_OF + SPROUT_CONSTEXPR result_type +#else + SPROUT_CONSTEXPR typename impl::expr_param +#endif + operator()( + typename impl::expr_param e, + typename impl::state_param, + typename impl::data_param + ) const + { + return e; + } + }; + }; + + // + // unary_expr + // + template + struct unary_expr + : public sprout::breed::transform, int> + { + public: + typedef Tag breed_tag; + typedef sprout::breed::expr, 1> type; + typedef sprout::breed::basic_expr, 1> breed_grammar; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + public: + template + struct impl + : public sprout::breed::detail::pass_through_impl + {}; + }; + + // + // binary_expr + // + template + struct binary_expr + : public sprout::breed::transform, int> + { + public: + typedef Tag breed_tag; + typedef sprout::breed::expr, 2> type; + typedef sprout::breed::basic_expr, 2> breed_grammar; + public: + template + struct breed_child + : public sprout::tppack_at + {}; + public: + template + struct impl + : public sprout::breed::detail::pass_through_impl + {}; + }; + +# define SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(op) \ + template \ + struct op \ + : public sprout::breed::transform, int> \ + { \ + public: \ + typedef sprout::breed::tag::op breed_tag; \ + typedef sprout::breed::expr, 1> type; \ + typedef sprout::breed::basic_expr, 1> breed_grammar; \ + public: \ + template \ + struct breed_child \ + : public sprout::tppack_at \ + {}; \ + public: \ + template \ + struct impl \ + : public sprout::breed::detail::pass_through_impl \ + {}; \ + }; +# define SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(op) \ + template \ + struct op \ + : public sprout::breed::transform, int> \ + { \ + public: \ + typedef sprout::breed::tag::op breed_tag; \ + typedef sprout::breed::expr, 2> type; \ + typedef sprout::breed::basic_expr, 2> breed_grammar; \ + public: \ + template \ + struct breed_child \ + : public sprout::tppack_at \ + {}; \ + public: \ + template \ + struct impl \ + : public sprout::breed::detail::pass_through_impl \ + {}; \ + }; + + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(unary_plus) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(negate) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(dereference) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(complement) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(address_of) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(logical_not) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(pre_inc) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(pre_dec) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(post_inc) + SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(post_dec) + + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_left) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_right) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(multiplies) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(divides) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(modulus) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(plus) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(minus) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(less) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(greater) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(less_equal) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(greater_equal) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(equal_to) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(not_equal_to) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(logical_or) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(logical_and) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_or) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_and) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_xor) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(comma) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(mem_ptr) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_left_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_right_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(multiplies_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(divides_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(modulus_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(plus_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(minus_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(subscript) + SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(member) + +# undef SPROUT_BREED_DEFINE_UNARY_METAFUNCTION +# undef SPROUT_BREED_DEFINE_BINARY_METAFUNCTION + + // + // function + // + template + struct function + : public sprout::breed::transform< + sprout::breed::function, + int + > + { + public: + typedef sprout::breed::tag::function breed_tag; + typedef sprout::breed::expr< + sprout::breed::tag::function, sprout::breed::list, + sizeof...(Args) + > type; + typedef sprout::breed::basic_expr< + sprout::breed::tag::function, sprout::breed::list, + sizeof...(Args) + > breed_grammar; + public: + template + struct breed_child { + public: + typedef std::conditional< + N < sizeof...(Args), + sprout::tppack_at, + sprout::breed::detail::if_vararg::type> + >::type::type + }; + template + struct impl + : public sprout::breed::detail::pass_through_impl + {}; + }; + + // + // nary_expr + // + template + struct nary_expr + : public sprout::breed::transform< + sprout::breed::nary_expr, + int + > + { + public: + typedef Tag breed_tag; + typedef sprout::breed::expr< + Tag, + sprout::breed::list, + sizeof...(Args) + > type; + typedef sprout::breed::basic_expr< + Tag, + sprout::breed::list, + sizeof...(Args) + > breed_grammar; + public: + template + struct breed_child { + public: + typedef std::conditional< + N < sizeof...(Args), + sprout::tppack_at, + sprout::breed::detail::if_vararg::type> + >::type::type + }; + template + struct impl + : public sprout::breed::detail::pass_through_impl + {}; + }; + + namespace detail { + template class T, typename... Args> + struct is_callable_, sizeof...(Args)> + : public std::is_same< + typename sprout::tppack_at::type, + sprout::breed::callable + > + {}; + } // namespace detail + + namespace result_of { + // + // child_c + // + template + struct child_c { + static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c"); + public: + typedef typename Expr::template breed_child::type value_type; + typedef typename sprout::breed::detail::expr_traits::value_type type; + }; + template + struct child_c { + static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c"); + public: + typedef typename Expr::template breed_child::type value_type; + typedef typename detail::expr_traits::reference type; + public: + static type call(Expr& e) { + return e.proto_base().breed child(); + } + }; + template + struct child_c { + static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c"); + public: + typedef typename Expr::template breed_child::type value_type; + typedef typename detail::expr_traits::const_reference type; + public: + static SPROUT_CONSTEXPR type call(Expr const& e) { + return e.proto_base().breed child(); + } + }; + } // namespace result_of + + namespace functional { + // + // as_expr + // + template + struct as_expr { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + typedef typename Domain::template as_expr::result_type type; + }; + template + struct result { + typedef typename Domain::template as_expr::result_type type; + }; + public: + template + SPROUT_CONSTEXPR typename std::add_const< + typename result::type + >::type operator()(T const& t) const { + return typename Domain::template as_expr()(t); + } + template + typename std::add_const< + typename result::type + >::type operator()(T& t) const { + return typename Domain::template as_expr()(t); + } + }; + + // + // as_child + // + template + struct as_child { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename Domain::template as_child::result_type type; + }; + template + struct result { + public: + typedef typename Domain::template as_child::result_type type; + }; + public: + template + SPROUT_CONSTEXPR typename std::add_const< + typename result::type + >::type operator()(T const& t) const { + return typename Domain::template as_child()(t); + } + template + typename std::add_const< + typename result::type + >::type operator()(T& t) const { + return typename Domain::template as_child()(t); + } + }; + + // + // child_c + // + template + struct child_c { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename result_of::child_c::type type; + }; + public: + template + SPROUT_CONSTEXPR typename result_of::child_c::type operator()(Expr const& e) const { + return result_of::child_c::call(e); + } + template + typename result_of::child_c::type operator()(Expr& e) const { + return result_of::child_c::call(e); + } + }; + + // + // child + // + template + struct child { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename result_of::child::type type; + }; + public: + template + SPROUT_CONSTEXPR typename result_of::child::type operator()(Expr const& e) const { + return result_of::child::call(e); + } + template + typename result_of::child::type operator()(Expr const& e) const { + return result_of::child::call(e); + } + }; + + // + // value + // + struct value { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename result_of::value::type type; + }; + public: + template + SPROUT_CONSTEXPR typename result_of::value::type operator()(Expr const& e) const { + return e.breed_base().template child<0>(); + } + template + typename result_of::value::type operator()(Expr& e) const { + return e.breed_base().template child<0>(); + } + }; + + // + // left + // + struct left { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename result_of::left::type type; + }; + public: + template + SPROUT_CONSTEXPR typename result_of::value::type operator()(Expr const& e) const { + return e.breed_base().template child<0>(); + } + template + typename result_of::value::type operator()(Expr& e) const { + return e.breed_base().template child<0>(); + } + }; + + // + // right + // + struct right { + public: + SPROUT_BREED_CALLABLE() + public: + template + struct result; + template + struct result { + public: + typedef typename result_of::right::type type; + }; + public: + template + SPROUT_CONSTEXPR typename result_of::value::type operator()(Expr const& e) const { + return e.breed_base().template child<1>(); + } + template + typename result_of::value::type operator()(Expr& e) const { + return e.breed_base().template child<1>(); + } + }; + } // namespace functional + + // + // as_expr + // + template + SPROUT_CONSTEXPR typename std::add_const< + typename sprout::breed::result_of::as_expr::type + >::type as_expr(T const& t) { + return sprout::breed::default_domain::as_expr()(t); + } + template + typename std::add_const< + typename sprout::breed::result_of::as_expr::type + >::type as_expr(T& t) { + return sprout::breed::default_domain::as_expr()(t); + } + template + SPROUT_CONSTEXPR typename std::add_const< + typename sprout::breed::result_of::as_expr::type + >::type as_expr(T const& t) { + return typename Domain::template as_expr()(t); + } + template + typename std::add_const< + typename sprout::breed::result_of::as_expr::type + >::type as_expr(T& t) { + return typename Domain::template as_expr()(t); + } + + // + // as_child + // + template + SPROUT_CONSTEXPR typename std::add_const< + typename sprout::breed::result_of::as_child::type + >::type as_child(T const& t) + { + return sprout::breed::default_domain::as_child()(t); + } + template + typename std::add_const< + typename sprout::breed::result_of::as_child::type + >::type as_child(T& t) + { + return sprout::breed::default_domain::as_child()(t); + } + template + SPROUT_CONSTEXPR typename std::add_const< + typename sprout::breed::result_of::as_child::type + >::type as_child(T const& t) + { + return typename Domain::template as_child()(t); + } + template + typename std::add_const< + typename sprout::breed::result_of::as_child::type + >::type as_child(T& t) + { + return typename Domain::template as_child()(t); + } + + // + // child + // + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::child::type child(Expr const& e) { + return sprout::breed::result_of::child::call(e); + } + template + typename sprout::breed::result_of::child::type child(Expr& e) { + return sprout::breed::result_of::child::call(e); + } + template + SPROUT_CONSTEXPR typename sprout::breed::detail::expr_traits< + typename Expr2::breed_base_expr:template breed_child<0>::type + >::const_reference child(Expr2 const& expr2) { + return expr2.breed_base().template child<0>(); + } + template + typename sprout::breed::detail::expr_traits< + typename Expr2::breed_base_expr:template breed_child<0>::type + >::reference child(Expr2& expr2) { + return expr2.breed_base().template child<0>(); + } + + // + // child_c + // + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::child_c::type child_c(Expr const& e) { + return sprout::breed::result_of::child_c::call(e); + } + template + typename sprout::breed::result_of::child_c::type child_c(Expr& e) { + return sprout::breed::result_of::child_c::call(e); + } + + // + // value + // + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::value::type value(Expr const& e) { + return e.breed_base().template child<0>(); + } + template + typename sprout::breed::result_of::value::type value(Expr& e) { + return e.breed_base().template child<0>(); + } + + // + // left + // + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::left::type left(Expr const& e) { + return e.breed_base().template child<0>(); + } + template + typename sprout::breed::result_of::left::type left(Expr& e) { + return e.breed_base().template child<0>(); + } + + // + // right + // + template + SPROUT_CONSTEXPR typename sprout::breed::result_of::right::type right(Expr const& e) { + return e.breed_base().template child<1>(); + } + template + typename sprout::breed::result_of::right::type right(Expr& e) { + return e.breed_base().template child<1>(); + } + + // + // is_callable + // + template + struct is_callable > + : public std::true_type + {}; + template + struct is_callable > + : public std::true_type + {}; + template + struct is_callable > + : public std::true_type + {}; + template + struct is_callable > + : public std::true_type + {}; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_TRAITS_HPP diff --git a/sprout/breed/transform/call.hpp b/sprout/breed/transform/call.hpp new file mode 100644 index 00000000..86c23d5e --- /dev/null +++ b/sprout/breed/transform/call.hpp @@ -0,0 +1,393 @@ +#ifndef SPROUT_BREED_TRANSFORM_CALL_HPP +#define SPROUT_BREED_TRANSFORM_CALL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + // + // call + // + template + struct call + : public PrimitiveTransform + {}; + template + struct call + : public sprout::breed::transform > + { + public: + template + struct impl2 + : public sprout::breed::transform_impl + { + public: + typedef typename sprout::breed::detail::std_result_of::type result_type; + public: + SPROUT_CONSTEXPR result_type operator()( + typename impl2::expr_param, + typename impl2::state_param, + typename impl2::data_param + ) const + { + return Fun()(); + } + }; + template + struct impl2 + : public Fun::template impl + {}; + template + struct impl + : public impl2::value> + {}; + }; + template + struct call + : public sprout::breed::transform > + { + public: + template + struct impl2 + : public sprout::breed::transform_impl + { + private: + template + struct a_ { + public: + typedef typename sprout::breed::when::template impl< + Expr, + State, + Data + > type; + }; + template + struct fun_ { + public: + typedef Fun type(typename a_::type::result_type...); + }; + template + struct function_ + : public sprout::breed::detail::poly_function_traits< + Fun, + typename fun_::type + > + {}; + public: + template + struct a { + public: + typedef typename a_::type>::type::result_type type; + }; + typedef function_ function_traits; + typedef typename function_traits::result_type result_type; + SPROUT_CONSTEXPR result_type operator ()( + typename impl2::expr_param e, + typename impl2::state_param s, + typename impl2::data_param d + ) const + { + return typename function_traits::function_type()( + sprout::breed::detail::as_lvalue(a_()(e, s, d)) + ); + } + }; + template + struct impl2 + : public sprout::breed::transform_impl + { + private: + template + struct a_ { + public: + typedef typename sprout::breed::when::template impl< + Expr, + State, + Data + > type; + }; + typedef Fun::template impl::type, State, Data> function_; + public: + template + struct a { + public: + typedef typename a_::type>::type::result_type type; + }; + typedef template function_::result_type result_type; + SPROUT_CONSTEXPR result_type operator ()( + typename impl2::expr_param e, + typename impl2::state_param s, + typename impl2::data_param d + ) const + { + return function_()( + typename a_::type()(e, s, d), + s, + d + ); + } + }; + template + struct impl + : public impl2::value> + {}; + }; + template + struct call + : public sprout::breed::transform > + { + public: + template + struct impl2 + : public sprout::breed::transform_impl + { + private: + template + struct a_ { + public: + typedef typename sprout::breed::when::template impl< + Expr, + State, + Data + > type; + }; + template + struct fun_ { + public: + typedef Fun type(typename a_::type::result_type...); + }; + template + struct function_ + : public sprout::breed::detail::poly_function_traits< + Fun, + typename fun_::type + > + {}; + public: + template + struct a { + public: + typedef typename a_::type>::type::result_type type; + }; + typedef function_ function_traits; + typedef typename function_traits::result_type result_type; + SPROUT_CONSTEXPR result_type operator ()( + typename impl2::expr_param e, + typename impl2::state_param s, + typename impl2::data_param d + ) const + { + return typename function_traits::function_type()( + sprout::breed::detail::as_lvalue(a_()(e, s, d)), + sprout::breed::detail::as_lvalue(a_()(e, s, d)) + ); + } + }; + template + struct impl2 + : public sprout::breed::transform_impl + { + private: + template + struct a_ { + public: + typedef typename sprout::breed::when::template impl< + Expr, + State, + Data + > type; + }; + typedef Fun::template impl::type, typename a_::type, Data> function_; + public: + template + struct a { + public: + typedef typename a_::type>::type::result_type type; + }; + typedef template function_::result_type result_type; + SPROUT_CONSTEXPR result_type operator ()( + typename impl2::expr_param e, + typename impl2::state_param s, + typename impl2::data_param d + ) const + { + return function_()( + typename a_::type()(e, s, d), + typename a_::type()(e, s, d), + d + ); + } + }; + template + struct impl + : public impl2::value> + {}; + }; + template + struct call + : public sprout::breed::transform > + { + public: + template + struct impl2 + : public sprout::breed::transform_impl + { + private: + template + struct a_ { + public: + typedef typename sprout::breed::when::template impl< + Expr, + State, + Data + > type; + }; + template + struct fun_ { + public: + typedef Fun type(typename a_::type::result_type...); + }; + template + struct function_ + : public sprout::breed::detail::poly_function_traits< + Fun, + typename fun_::type + > + {}; + public: + template + struct a { + public: + typedef typename a_::type>::type::result_type type; + }; + typedef function_ function_traits; + typedef typename function_traits::result_type result_type; + SPROUT_CONSTEXPR result_type operator ()( + typename impl2::expr_param e, + typename impl2::state_param s, + typename impl2::data_param d + ) const + { + return typename function_traits::function_type()( + sprout::breed::detail::as_lvalue(a_()(e, s, d)), + sprout::breed::detail::as_lvalue(a_()(e, s, d)), + sprout::breed::detail::as_lvalue(a_()(e, s, d)) + ); + } + }; + template + struct impl2 + : public sprout::breed::transform_impl + { + private: + template + struct a_ { + public: + typedef typename sprout::breed::when::template impl< + Expr, + State, + Data + > type; + }; + typedef Fun::template impl::type, typename a_::type, typename a_::type> function_; + public: + template + struct a { + public: + typedef typename a_::type>::type::result_type type; + }; + typedef template function_::result_type result_type; + SPROUT_CONSTEXPR result_type operator ()( + typename impl2::expr_param e, + typename impl2::state_param s, + typename impl2::data_param d + ) const + { + return function_()( + typename a_::type()(e, s, d), + typename a_::type()(e, s, d), + typename a_::type()(e, s, d) + ); + } + }; + template + struct impl + : public impl2::value> + {}; + }; + template + struct call + : public sprout::breed::transform > + { + public: + template + struct impl + : public sprout::breed::transform_impl + { + private: + template + struct a_ { + public: + typedef typename sprout::breed::when::template impl< + Expr, + State, + Data + > type; + }; + template + struct fun_ { + public: + typedef Fun type(typename a_::type::result_type...); + }; + template + struct function_ + : public sprout::breed::detail::poly_function_traits< + Fun, + typename fun_::type + > + {}; + public: + template + struct a { + public: + typedef typename a_::type>::type type; + }; + template + struct b { + public: + typedef typename a_::type>::type::result_type type; + }; + typedef function_ function_traits; + typedef typename function_traits::result_type result_type; + SPROUT_CONSTEXPR result_type operator ()( + typename impl2::expr_param e, + typename impl2::state_param s, + typename impl2::data_param d + ) const + { + return typename function_traits::function_type()( + sprout::breed::detail::as_lvalue(typename a_::type()(e, s, d))... + ); + } + }; + }; + // + // is_callable + // + template + struct is_callable > + : public std::true_type + {}; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_TRANSFORM_CALL_HPP diff --git a/sprout/breed/transform/impl.hpp b/sprout/breed/transform/impl.hpp new file mode 100644 index 00000000..33c5698c --- /dev/null +++ b/sprout/breed/transform/impl.hpp @@ -0,0 +1,166 @@ +#ifndef SPROUT_BREED_TRANSFORM_IMPL_HPP +#define SPROUT_BREED_TRANSFORM_IMPL_HPP + +#include +#include + +namespace sprout { + namespace breed { + // + // SPROUT_BREED_TRANSFORM_ + // +# define SPROUT_BREED_TRANSFORM_(PrimitiveTransform, X) \ + public: \ + SPROUT_BREED_CALLABLE() \ + typedef X breed_is_transform_; \ + typedef PrimitiveTransform transform_type; \ + public: \ + template \ + struct result { \ + public: \ + typedef typename sprout::breed::detail::apply_transform::result_type type; \ + }; \ + template \ + SPROUT_CONSTEXPR typename sprout::breed::detail::apply_transform< \ + transform_type(Expr const&) \ + >::result_type operator()(Expr&& e) const { \ + return sprout::breed::detail::apply_transform< \ + transform_type(Expr const&) \ + >()(e, 0, 0); \ + } \ + template \ + SPROUT_CONSTEXPR typename sprout::breed::detail::apply_transform< \ + transform_type(Expr const&, State const&) \ + >::result_type operator()(Expr&& e, State&& s) const \ + { \ + return sprout::breed::detail::apply_transform< \ + transform_type(Expr const&, State const&) \ + >()(e, s, 0); \ + } \ + template \ + SPROUT_CONSTEXPR typename sprout::breed::detail::apply_transform< \ + transform_type(Expr const&, State const&, Data const&) \ + >::result_type operator()(Expr&& e, State&& s, Data&& d) const { \ + return sprout::breed::detail::apply_transform< \ + transform_type(Expr const&, State const&, Data const&) \ + >()(e, s, d); \ + } + // + // SPROUT_BREED_TRANSFORM + // +# define SPROUT_BREED_TRANSFORM(PrimitiveTransform) \ + SPROUT_BREED_TRANSFORM_(PrimitiveTransform, void) + + namespace detail { + template + struct apply_transform; + template + struct apply_transform + : public PrimitiveTransform::template impl + {}; + template + struct apply_transform + : public PrimitiveTransform::template impl + {}; + template + struct apply_transform + : public PrimitiveTransform::template impl + {}; + } // namespace detail + + // + // transform + // + template + struct transform { + public: + SPROUT_BREED_TRANSFORM_(PrimitiveTransform, X); + }; + + // + // transform_impl + // + template + struct transform_impl { + public: + typedef Expr const expr; + typedef Expr const& expr_param; + typedef State const state; + typedef State const& state_param; + typedef Data const data; + typedef Data const& data_param; + }; + template + struct transform_impl { + public: + typedef Expr expr; + typedef Expr& expr_param; + typedef State const state; + typedef State const& state_param; + typedef Data const data; + typedef Data const& data_param; + }; + template + struct transform_impl { + public: + typedef Expr const expr; + typedef Expr const& expr_param; + typedef State state; + typedef State& state_param; + typedef Data const data; + typedef Data const& data_param; + }; + template + struct transform_impl { + public: + typedef Expr const expr; + typedef Expr const& expr_param; + typedef State const state; + typedef State const& state_param; + typedef Data data; + typedef Data& data_param; + }; + template + struct transform_impl { + public: + typedef Expr expr; + typedef Expr& expr_param; + typedef State state; + typedef State& state_param; + typedef Data const data; + typedef Data const& data_param; + }; + template + struct transform_impl { + public: + typedef Expr expr; + typedef Expr& expr_param; + typedef State const state; + typedef State const& state_param; + typedef Data data; + typedef Data& data_param; + }; + template + struct transform_impl { + public: + typedef Expr const expr; + typedef Expr const& expr_param; + typedef State state; + typedef State& state_param; + typedef Data data; + typedef Data& data_param; + }; + template + struct transform_impl { + public: + typedef Expr expr; + typedef Expr& expr_param; + typedef State state; + typedef State& state_param; + typedef Data data; + typedef Data& data_param; + }; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_TRANSFORM_IMPL_HPP diff --git a/sprout/breed/transform/pass_through.hpp b/sprout/breed/transform/pass_through.hpp new file mode 100644 index 00000000..b0459e9b --- /dev/null +++ b/sprout/breed/transform/pass_through.hpp @@ -0,0 +1,129 @@ +#ifndef SPROUT_BREED_TRANSFORM_PASS_THROUGH_HPP +#define SPROUT_BREED_TRANSFORM_PASS_THROUGH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + namespace detail { + template< + typename Grammar, + typename Expr, + typename State, + typename Data, + long Arity = sprout::breed::arity_of::value + > + struct pass_through_impl + : public sprout::breed::transform_impl + { + public: + typedef typename pass_through_impl::expr unref_expr; + private: + template + struct list_impl {}; + template + struct list_impl > { + public: + typedef sprout::breed::list< + typename Grammar::template breed_child::type::template impl< + typename sprout::breed::result_of::child_c::type, + State, + Data + >::result_type... + > type; + }; + public: + typedef typename sprout::breed::base_expr< + typename unref_expr::breed_domain, + typename unref_expr::breed_tag, + typename list_impl::type>::type + >::type expr_type; + typedef typename unref_expr::breed_generator breed_generator; + typedef typename sprout::breed::detail::std_result_of< + breed_generator(expr_type) + >::type result_type; + private: + template + SPROUT_CONSTEXPR result_type call_impl( + typename pass_through_impl::expr_param e, + typename pass_through_impl::state_param s, + typename pass_through_impl::data_param d, + sprout::index_tuple + ) const + { + return breed_generator()( + expr_type( + typename Grammar::template breed_child::type::template impl< + typename sprout::breed::result_of::child_c::type, + State, + Data + >()(e.proto_base().template child(), s, d)... + ) + ); + } + public: + SPROUT_CONSTEXPR result_type operator()( + typename pass_through_impl::expr_param e, + typename pass_through_impl::state_param s, + typename pass_through_impl::data_param d + ) const + { + return call_impl(e, s, d, typename sprout::index_range<0, Arity>::type()); + } + }; + template + struct pass_through_impl + : public sprout::breed::transform_impl + { + public: + typedef Expr result_type; + public: +#ifdef SPROUT_BREED_STRICT_RESULT_OF + SPROUT_CONSTEXPR result_type +#else + SPROUT_CONSTEXPR typename pass_through_impl::expr_param +#endif + operator()( + typename pass_through_impl::expr_param e, + typename pass_through_impl::state_param, + typename pass_through_impl::data_param + ) const + { + return e; + } + }; + + } // namespace detail + + // + // pass_through + // + template + struct pass_through + : public sprout::breed::transform > + { + public: + template + struct impl + : public sprout::breed::detail::pass_through_impl + {}; + }; + + // + // is_callable + // + template + struct is_callable > + : public std::true_type + {}; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_TRANSFORM_PASS_THROUGH_HPP diff --git a/sprout/breed/transform/when.hpp b/sprout/breed/transform/when.hpp new file mode 100644 index 00000000..91b980a7 --- /dev/null +++ b/sprout/breed/transform/when.hpp @@ -0,0 +1,126 @@ +#ifndef SPROUT_BREED_TRANSFORM_WHEN_HPP +#define SPROUT_BREED_TRANSFORM_WHEN_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace breed { + // + // when + // + template + struct when + : public PrimitiveTransform + { + public: + typedef Grammar first; + typedef PrimitiveTransform second; + typedef typename Grammar::breed_grammar breed_grammar; + }; + template + struct when + : public sprout::breed::when + {}; + template + struct when + : public sprout::breed::transform > + { + public: + typedef Grammar first; + typedef external_transform second; + typedef typename Grammar::breed_grammar breed_grammar; + public: + template + struct impl + : public Data::template when::template impl + {}; + template + struct impl + : public Data::template when::template impl + {}; + }; + template + struct when + : public sprout::breed::transform > + { + public: + typedef Grammar first; + typedef R second(Args...); + typedef typename Grammar::breed_grammar breed_grammar; + public: + template + struct impl + : public sprout::breed::transform_impl + { + public: + typedef typename std::conditional< + sprout::breed::is_callable::value, + sprout::breed::call, + sprout::breed::make + >::type which; + typedef typename which::template impl::result_type result_type; + public: + SPROUT_CONSTEXPR result_type operator()( + typename impl::expr_param e, + typename impl::state_param s, + typename impl::data_param d + ) const + { + return typename which::template impl()(e, s, d); + } + }; + }; + // + // is_callable + // + template + struct is_callable > + : public std::true_type + {}; + // + // otherwise + // + template + struct otherwise + : public sprout::breed::when + {}; + // + // external_transforms + // + template + struct external_transforms { + public: + typedef sprout::types::type_tuple map_type; + private: + template + struct map_pred { + public: + template + struct apply + : public std::is_same + {}; + }; + public: + template + struct when + : public sprout::breed::when< + sprout::breed::_, + sprout::types::deref< + typename sprout::types::find_if >::type + >::type + > + {}; + }; + } // namespace breed +} // namespace sprout + +#endif // #ifndef SPROUT_BREED_TRANSFORM_WHEN_HPP diff --git a/sprout/config.hpp b/sprout/config.hpp index d83aa2fb..b22aa4ee 100644 --- a/sprout/config.hpp +++ b/sprout/config.hpp @@ -17,6 +17,12 @@ # define SPROUT_NOEXCEPT_EXPR(EXPR) #endif // #ifndef SPROUT_CONFIG_DISABLE_NOEXCEPT +#ifndef SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES +# define SPROUT_USE_TEMPLATE_ALIASES 1 +#else // #ifndef SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES +# define SPROUT_USE_TEMPLATE_ALIASES 0 +#endif // #ifndef SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES + #ifndef SPROUT_CONFIG_USE_SSCRISK_CEL # define HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT_DETAIL # define HDR_ALGORITHM_SSCRISK_CEL_OR_SPROUT_DETAIL @@ -29,10 +35,13 @@ # define NS_SSCRISK_CEL_OR_SPROUT_DETAIL sscrisk::cel #endif // #ifndef SPROUT_CONFIG_USE_SSCRISK_CEL -#ifndef SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION -# define SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION 0 -#else // #ifndef SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION +#ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION # define SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION 1 -#endif // #ifndef SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION +#else // #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION +# ifdef SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION +# error config conflict: SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION, SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION +# endif // #ifndef SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION +# define SPROUT_USE_INDEX_ITERATOR_IMPLEMENTATION 0 +#endif // #ifndef SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION #endif // #ifndef SPROUT_CONFIG_HPP diff --git a/sprout/preprocessor/cat.hpp b/sprout/preprocessor/cat.hpp new file mode 100644 index 00000000..8835d23c --- /dev/null +++ b/sprout/preprocessor/cat.hpp @@ -0,0 +1,14 @@ +#ifndef SPROUT_PREPROCESSOR_CAT_HPP +#define SPROUT_PREPROCESSOR_CAT_HPP + +#include + +#define SPROUT_PP_CAT_I(a, b) a ## b + +// +// SPROUT_PP_CAT +// +#define SPROUT_PP_CAT(a, b) SPROUT_PP_CAT_I(a, b) + +#endif // #ifndef SPROUT_PREPROCESSOR_CAT_HPP + diff --git a/sprout/string.hpp b/sprout/string.hpp index e694d5b4..e3f09f90 100644 --- a/sprout/string.hpp +++ b/sprout/string.hpp @@ -1098,4 +1098,6 @@ namespace std { }; } // namespace std +#include + #endif // #ifndef SPROUT_STRING_HPP diff --git a/sprout/string/alias.hpp b/sprout/string/alias.hpp index c981d131..b80d3a82 100644 --- a/sprout/string/alias.hpp +++ b/sprout/string/alias.hpp @@ -1,10 +1,13 @@ #ifndef SPROUT_STRING_ALIAS_HPP #define SPROUT_STRING_ALIAS_HPP -#include #include #include +#if SPROUT_USE_TEMPLATE_ALIASES + +#include + namespace sprout { // // string @@ -28,4 +31,6 @@ namespace sprout { using u32string = sprout::basic_string; } // namespace sprout +#endif // #if SPROUT_USE_TEMPLATE_ALIASES + #endif // #ifndef SPROUT_STRING_ALIAS_HPP diff --git a/sprout/type/boost/mpl/string.hpp b/sprout/type/boost/mpl/string.hpp new file mode 100644 index 00000000..977c87be --- /dev/null +++ b/sprout/type/boost/mpl/string.hpp @@ -0,0 +1,62 @@ +#ifndef SPROUT_TYPE_BOOST_MPL_STRING_HPP +#define SPROUT_TYPE_BOOST_MPL_STRING_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // begin + // + template + struct begin > + : public boost::mpl::begin > + {}; + // + // end + // + template + struct end > + : public boost::mpl::end > + {}; + + // + // tuple_size + // + template + struct tuple_size > + : public boost::mpl::size > + {}; + // + // tuple_element + // + template + struct tuple_element > + : public boost::mpl::at_c, I> + {}; + + // + // next + // + template + struct next > + : public boost::mpl::next > + {}; + // + // prev + // + template + struct prev > + : public boost::mpl::prior > + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_BOOST_MPL_STRING_HPP diff --git a/sprout/type/boost/mpl/v_iter.hpp b/sprout/type/boost/mpl/v_iter.hpp new file mode 100644 index 00000000..1c66c3ba --- /dev/null +++ b/sprout/type/boost/mpl/v_iter.hpp @@ -0,0 +1,29 @@ +#ifndef SPROUT_TYPE_BOOST_MPL_V_ITER_HPP +#define SPROUT_TYPE_BOOST_MPL_V_ITER_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // next + // + template + struct next > + : public boost::mpl::next > + {}; + // + // prev + // + template + struct prev > + : public boost::mpl::prior > + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_BOOST_MPL_V_ITER_HPP diff --git a/sprout/type/boost/mpl/vector.hpp b/sprout/type/boost/mpl/vector.hpp new file mode 100644 index 00000000..7048cd51 --- /dev/null +++ b/sprout/type/boost/mpl/vector.hpp @@ -0,0 +1,45 @@ +#ifndef SPROUT_TYPE_BOOST_MPL_VECTOR_HPP +#define SPROUT_TYPE_BOOST_MPL_VECTOR_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // begin + // + template + struct begin > + : public boost::mpl::begin > + {}; + // + // end + // + template + struct end > + : public boost::mpl::end > + {}; + + // + // tuple_size + // + template + struct tuple_size > + : public boost::mpl::size > + {}; + // + // tuple_element + // + template + struct tuple_element > + : public boost::mpl::at_c, I> + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_BOOST_MPL_VECTOR_HPP diff --git a/sprout/type/boost/mpl/vector_c.hpp b/sprout/type/boost/mpl/vector_c.hpp new file mode 100644 index 00000000..07823b19 --- /dev/null +++ b/sprout/type/boost/mpl/vector_c.hpp @@ -0,0 +1,45 @@ +#ifndef SPROUT_TYPE_BOOST_MPL_VECTOR_C_HPP +#define SPROUT_TYPE_BOOST_MPL_VECTOR_C_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // begin + // + template + struct begin > + : public boost::mpl::begin > + {}; + // + // end + // + template + struct end > + : public boost::mpl::end > + {}; + + // + // tuple_size + // + template + struct tuple_size > + : public boost::mpl::size > + {}; + // + // tuple_element + // + template + struct tuple_element > + : public boost::mpl::at_c, I> + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_BOOST_MPL_VECTOR_C_HPP diff --git a/sprout/type/integral_array.hpp b/sprout/type/integral_array.hpp new file mode 100644 index 00000000..3da3e910 --- /dev/null +++ b/sprout/type/integral_array.hpp @@ -0,0 +1,44 @@ +#ifndef SPROUT_TYPE_INTEGRAL_ARRAY_HPP +#define SPROUT_TYPE_INTEGRAL_ARRAY_HPP + +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // integral_array + // + template + struct integral_array + : public sprout::types::type_tuple...> + { + public: + typedef T value_type; + }; + } // namespace types +} // namespace sprout + +namespace std { + // + // tuple_size + // + template + struct tuple_size > + : public std::tuple_size...> > + {}; + + // + // tuple_element + // + template + struct tuple_element > + : public std::tuple_element...> > + {}; +} // namespace std + +#endif // #ifndef SPROUT_TYPE_INTEGRAL_ARRAY_HPP diff --git a/sprout/type/iterator.hpp b/sprout/type/iterator.hpp index fd7f2f7f..2809eb9f 100644 --- a/sprout/type/iterator.hpp +++ b/sprout/type/iterator.hpp @@ -5,5 +5,6 @@ #include #include #include +#include #endif // #ifndef SPROUT_TYPE_ITERATOR_HPP diff --git a/sprout/type/iterator/distance.hpp b/sprout/type/iterator/distance.hpp new file mode 100644 index 00000000..70d5ecbe --- /dev/null +++ b/sprout/type/iterator/distance.hpp @@ -0,0 +1,51 @@ +#ifndef SPROUT_TYPE_ITERATOR_DISTANCE_HPP +#define SPROUT_TYPE_ITERATOR_DISTANCE_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // distance + // + namespace detail { + template + struct distance_impl; + template + struct distance_impl< + First, + Last, + N, + typename std::enable_if< + std::is_same::value + >::type + > + : public std::integral_constant + {}; + template + struct distance_impl< + First, + Last, + N, + typename std::enable_if< + !std::is_same::value + >::type + > + : public sprout::types::detail::distance_impl< + typename sprout::types::next::type, + Last, + N + 1 + > + {}; + } // namespace detail + template + struct distance + : public sprout::types::detail::distance_impl + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_ITERATOR_DISTANCE_HPP diff --git a/sprout/type/iterator/index_iterator.hpp b/sprout/type/iterator/index_iterator.hpp index 70252b34..07f1ca99 100644 --- a/sprout/type/iterator/index_iterator.hpp +++ b/sprout/type/iterator/index_iterator.hpp @@ -84,7 +84,10 @@ namespace sprout { struct index_iterator : public sprout::types::detail::index_iterator_impl , public std::integral_constant - {}; + { + public: + typedef typename sprout::types::detail::index_iterator_impl::type type; + }; } // namespace types } // namespace sprout diff --git a/sprout/type/iterator/next.hpp b/sprout/type/iterator/next.hpp index bcc969b0..7b2b61d0 100644 --- a/sprout/type/iterator/next.hpp +++ b/sprout/type/iterator/next.hpp @@ -8,7 +8,7 @@ namespace sprout { // // next // - template + template struct next { public: typedef typename Iterator::next type; diff --git a/sprout/type/iterator/prev.hpp b/sprout/type/iterator/prev.hpp index 8ed91cb2..13a5558d 100644 --- a/sprout/type/iterator/prev.hpp +++ b/sprout/type/iterator/prev.hpp @@ -8,7 +8,7 @@ namespace sprout { // // prev // - template + template struct prev { public: typedef typename Iterator::prev type; diff --git a/sprout/type/seq/algorithm.hpp b/sprout/type/seq/algorithm.hpp index fd3fd892..49fe480e 100644 --- a/sprout/type/seq/algorithm.hpp +++ b/sprout/type/seq/algorithm.hpp @@ -3,5 +3,6 @@ #include #include +#include #endif // #ifndef SPROUT_TYPE_SEQ_ALGORITHM_HPP diff --git a/sprout/type/seq/algorithm/find_if.hpp b/sprout/type/seq/algorithm/find_if.hpp new file mode 100644 index 00000000..6cd3ff0e --- /dev/null +++ b/sprout/type/seq/algorithm/find_if.hpp @@ -0,0 +1,71 @@ +#ifndef SPROUT_TYPE_SEQ_ALGORITHM_FIND_IF_HPP +#define SPROUT_TYPE_SEQ_ALGORITHM_FIND_IF_HPP + +#include +#include +#include + +namespace sprout { + namespace types { + namespace seq { + namespace detail { + template + struct find_if_impl; + template + struct find_if_impl< + First, + Last, + Predicate, + typename std::enable_if< + std::is_same::value + >::type + > { + public: + typedef Last type; + }; + template + struct find_if_impl< + First, + Last, + Predicate, + typename std::enable_if< + !std::is_same::value + && Predicate::template apply::type>::type::value + >::type + > { + public: + typedef First type; + }; + template + struct find_if_impl< + First, + Last, + Predicate, + typename std::enable_if< + !std::is_same::value + && !Predicate::template apply::type>::type::value + >::type + > + : public sprout::types::seq::detail::find_if_impl< + typename sprout::types::next::type, + Last, + Predicate + > + {}; + } // namespace detail + // + // find_if + // + template + struct find_if + : public sprout::types::seq::detail::find_if_impl< + typename sprout::types::begin::type, + typename sprout::types::end::type, + Predicate + > + {}; + } // namespace seq + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_SEQ_ALGORITHM_FIND_IF_HPP diff --git a/sprout/type/string.hpp b/sprout/type/string.hpp new file mode 100644 index 00000000..a3001631 --- /dev/null +++ b/sprout/type/string.hpp @@ -0,0 +1,44 @@ +#ifndef SPROUT_TYPE_STRING_HPP +#define SPROUT_TYPE_STRING_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // basic_string + // + template + struct basic_string + : public sprout::types::integral_array + {}; + } // namespace types +} // namespace sprout + +namespace std { + // + // tuple_size + // + template + struct tuple_size > + : public std::tuple_size > + {}; + + // + // tuple_element + // + template + struct tuple_element > + : public std::tuple_element > + {}; +} // namespace std + +#include +#include +#include + +#endif // #ifndef SPROUT_TYPE_STRING_HPP diff --git a/sprout/type/string/alias.hpp b/sprout/type/string/alias.hpp new file mode 100644 index 00000000..04e4863c --- /dev/null +++ b/sprout/type/string/alias.hpp @@ -0,0 +1,36 @@ +#ifndef SPROUT_TYPE_STRING_ALIAS_HPP +#define SPROUT_TYPE_STRING_ALIAS_HPP + +#include +#include + +#if SPROUT_USE_TEMPLATE_ALIASES + +namespace sprout { + namespace types { + // + // string + // + template + using string = sprout::types::basic_string; + // + // wstring + // + template + using wstring = sprout::types::basic_string; + // + // u16string + // + template + using u16string = sprout::types::basic_string; + // + // string + // + template + using u32string = sprout::types::basic_string; + } // namespace types +} // namespace sprout + +#endif // #if SPROUT_USE_TEMPLATE_ALIASES + +#endif // #ifndef SPROUT_TYPE_STRING_ALIAS_HPP diff --git a/sprout/type/string/to_string.hpp b/sprout/type/string/to_string.hpp new file mode 100644 index 00000000..85d961ef --- /dev/null +++ b/sprout/type/string/to_string.hpp @@ -0,0 +1,81 @@ +#ifndef SPROUT_TYPE_STRING_TO_STRING_HPP +#define SPROUT_TYPE_STRING_TO_STRING_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // to_string + // + template + struct to_string { + private: + typedef decltype(StringClass()()) string_type; + typedef sprout::fixed_container_traits traits_type; + private: + template + struct impl; + template + struct impl > { + public: + typedef sprout::types::basic_string< + typename traits_type::value_type, + (*sprout::next(sprout::begin(StringClass()()), Indexes))... + > type; + }; + public: + typedef typename impl< + typename sprout::index_range<0, sprout::size(StringClass()())>::type + >::type type; + }; + namespace detail { + template + struct string_typedef_impl { + public: + typedef typename std::decay::type result_type; + public: + SPROUT_CONSTEXPR result_type operator()(Src const& src) const { + return src; + } + }; + template + struct string_typedef_impl { + public: + typedef decltype(sprout::to_string(std::declval())) result_type; + public: + SPROUT_CONSTEXPR result_type operator()(Src const& src) const { + return sprout::to_string(src); + } + }; + } // namespace detail + // + // SPROUT_TYPES_STRING_TYPEDEF + // +# define SPROUT_TYPES_STRING_TYPEDEF(SOURCE, TYPE) \ + struct SPROUT_PP_CAT(SPROUT_TYPES_STRING_TYPEDEF_IMPL_, __LINE__) { \ + private: \ + typedef typename std::remove_reference::type src_type; \ + typedef sprout::types::detail::string_typedef_impl::value> impl_type; \ + public: \ + typedef typename impl_type::result_type result_type; \ + public: \ + SPROUT_CONSTEXPR result_type operator()() const { \ + return impl_type()(SOURCE); \ + } \ + }; \ + typedef typename sprout::types::to_string::type TYPE + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_STRING_TO_STRING_HPP diff --git a/sprout/type/string/to_string_constant.hpp b/sprout/type/string/to_string_constant.hpp new file mode 100644 index 00000000..ccbf3fca --- /dev/null +++ b/sprout/type/string/to_string_constant.hpp @@ -0,0 +1,67 @@ +#ifndef SPROUT_TYPE_STRING_TO_STRING_CONSTANT_HPP +#define SPROUT_TYPE_STRING_TO_STRING_CONSTANT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // to_string_constant + // + namespace detail { + struct is_nul { + public: + template + struct apply + : public std::false_type + {}; + template + struct apply::type> + : public std::true_type + {}; + }; + template + struct str_length + : public sprout::types::distance< + typename sprout::types::begin::type, + typename sprout::types::seq::find_if< + Sequence, + sprout::types::detail::is_nul + >::type + > + {}; + template + SPROUT_CONSTEXPR inline sprout::basic_string< + typename Sequence::value_type, + sprout::types::detail::str_length::value + > to_string_constant_impl(sprout::index_tuple) { + typedef sprout::basic_string< + typename Sequence::value_type, + sprout::types::detail::str_length::value + > type; + return type{ + {sprout::types::tuple_element::type::value...}, + sprout::types::detail::str_length::value + }; + } + } // namespace detail + template + SPROUT_CONSTEXPR inline sprout::basic_string< + typename Sequence::value_type, + sprout::types::detail::str_length::value + > to_string_constant() { + return sprout::types::detail::to_string_constant_impl( + typename sprout::index_range<0, sprout::types::detail::str_length::value>::type() + ); + } + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_STRING_TO_STRING_CONSTANT_HPP diff --git a/sprout/type/tuple.hpp b/sprout/type/tuple.hpp index c3cbd29f..c0ca255f 100644 --- a/sprout/type/tuple.hpp +++ b/sprout/type/tuple.hpp @@ -10,14 +10,14 @@ namespace sprout { // // begin // - template + template struct begin { typedef typename T::begin type; }; // // end // - template + template struct end { typedef typename T::end type; }; @@ -25,14 +25,14 @@ namespace sprout { // // tuple_size // - template + template struct tuple_size : public std::tuple_size {}; // // tuple_element // - template + template struct tuple_element : public std::tuple_element {}; diff --git a/sprout_user_config.hpp b/sprout_user_config.hpp index 7e97334d..39de7908 100644 --- a/sprout_user_config.hpp +++ b/sprout_user_config.hpp @@ -1,5 +1,7 @@ //#define SPROUT_CONFIG_DISABLE_CONSTEXPR //#define SPROUT_CONFIG_DISABLE_NOEXCEPT +//#define SPROUT_CONFIG_DISABLE_TEMPLATE_ALIASES //#define SPROUT_CONFIG_USE_SSCRISK_CEL +//#define SPROUT_CONFIG_DISABLE_SUPPORT_TEMPORARY_CONTAINER_ITERATION //#define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION