diff --git a/sprout/tuple.hpp b/sprout/tuple.hpp index 5bb157b4..ca3016d4 100644 --- a/sprout/tuple.hpp +++ b/sprout/tuple.hpp @@ -3,6 +3,6 @@ #include #include -#include +#include #endif // #ifndef SPROUT_TUPLE_HPP diff --git a/sprout/tuple/operation/append_back.hpp b/sprout/tuple/operation/append_back.hpp index d27582af..d264fa3b 100644 --- a/sprout/tuple/operation/append_back.hpp +++ b/sprout/tuple/operation/append_back.hpp @@ -4,8 +4,9 @@ #include #include #include -#include +#include #include +#include namespace sprout { namespace tuples { @@ -14,25 +15,9 @@ namespace sprout { // append_back // template - struct append_back { - private: - template - struct apply_impl; - template - struct apply_impl, sprout::index_tuple > - : public sprout::tuples::rebind_types< - Tuple - >::template apply< - typename sprout::tuples::tuple_element::type..., - typename sprout::tuples::tuple_element::type... - > - {}; - public: - typedef typename apply_impl< - typename sprout::index_range<0, sprout::tuples::tuple_size::value>::type, - typename sprout::index_range<0, sprout::tuples::tuple_size::value>::type - >::type type; - }; + struct append_back + : public sprout::types::append_back + {}; } // namespace result_of namespace detail { diff --git a/sprout/tuple/operation/append_front.hpp b/sprout/tuple/operation/append_front.hpp index 2028991b..de1e059a 100644 --- a/sprout/tuple/operation/append_front.hpp +++ b/sprout/tuple/operation/append_front.hpp @@ -4,8 +4,9 @@ #include #include #include -#include +#include #include +#include namespace sprout { namespace tuples { @@ -14,25 +15,9 @@ namespace sprout { // append_front // template - struct append_front { - private: - template - struct apply_impl; - template - struct apply_impl, sprout::index_tuple > - : public sprout::tuples::rebind_types< - Tuple - >::template apply< - typename sprout::tuples::tuple_element::type..., - typename sprout::tuples::tuple_element::type... - > - {}; - public: - typedef typename apply_impl< - typename sprout::index_range<0, sprout::tuples::tuple_size::value>::type, - typename sprout::index_range<0, sprout::tuples::tuple_size::value>::type - >::type type; - }; + struct append_front + : public sprout::types::append_front + {}; } // namespace result_of namespace detail { diff --git a/sprout/tuple/operation/push_back.hpp b/sprout/tuple/operation/push_back.hpp index a69a370d..91c875e7 100644 --- a/sprout/tuple/operation/push_back.hpp +++ b/sprout/tuple/operation/push_back.hpp @@ -4,8 +4,9 @@ #include #include #include -#include +#include #include +#include namespace sprout { namespace tuples { @@ -14,24 +15,9 @@ namespace sprout { // push_back // template - struct push_back { - private: - template - struct apply_impl; - template - struct apply_impl> - : public sprout::tuples::rebind_types< - Tuple - >::template apply< - typename sprout::tuples::tuple_element::type..., - T - > - {}; - public: - typedef typename apply_impl< - typename sprout::index_range<0, sprout::tuples::tuple_size::value>::type - >::type type; - }; + struct push_back + : public sprout::types::push_back + {}; } // namespace result_of namespace detail { diff --git a/sprout/tuple/operation/push_front.hpp b/sprout/tuple/operation/push_front.hpp index 8592a9a7..ae91ca92 100644 --- a/sprout/tuple/operation/push_front.hpp +++ b/sprout/tuple/operation/push_front.hpp @@ -4,8 +4,9 @@ #include #include #include -#include +#include #include +#include namespace sprout { namespace tuples { @@ -14,24 +15,9 @@ namespace sprout { // push_front // template - struct push_front { - private: - template - struct apply_impl; - template - struct apply_impl> - : public sprout::tuples::rebind_types< - Tuple - >::template apply< - T, - typename sprout::tuples::tuple_element::type... - > - {}; - public: - typedef typename apply_impl< - typename sprout::index_range<0, sprout::tuples::tuple_size::value>::type - >::type type; - }; + struct push_front + : public sprout::types::push_front + {}; } // namespace result_of namespace detail { diff --git a/sprout/tuple/traits.hpp b/sprout/tuple/traits.hpp index eab70a34..8aadb17f 100644 --- a/sprout/tuple/traits.hpp +++ b/sprout/tuple/traits.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace sprout { namespace tuples { @@ -24,20 +25,9 @@ namespace sprout { // rebind_types // template - struct rebind_types { - public: - template - struct apply; - }; - template - struct rebind_types > { - public: - template - struct apply { - public: - typedef sprout::tuples::tuple type; - }; - }; + struct rebind_types + : public sprout::types::rebind_types + {}; // // clone_functor @@ -93,7 +83,6 @@ namespace sprout { } // namespace tuples using sprout::tuples::tuple_traits; - using sprout::tuples::rebind_types; } // namespace sprout #endif // #ifndef SPROUT_TUPLE_TRAITS_HPP diff --git a/sprout/tuple/tuple.hpp b/sprout/tuple/tuple.hpp index 4b26406d..1661c759 100644 --- a/sprout/tuple/tuple.hpp +++ b/sprout/tuple/tuple.hpp @@ -229,7 +229,7 @@ namespace sprout { : inherited_type(static_cast&&>(t)) {} // tuple assignment - tuple& operator=(const tuple& rhs) { + tuple& operator=(tuple const& rhs) { static_cast(*this) = rhs; return *this; } @@ -248,7 +248,7 @@ namespace sprout { return *this; } // tuple swap - void swap(tuple& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(other.swap(other))) { + void swap(tuple& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(inherited_type::swap(other))) { inherited_type::swap(other); } }; @@ -426,4 +426,6 @@ namespace sprout { using sprout::tuples::get; } // namespace sprout +#include + #endif // #ifndef SPROUT_TUPLE_TUPLE_HPP diff --git a/sprout/tuple/tuple_comparison.hpp b/sprout/tuple/tuple_comparison.hpp index bbc97351..7d7d0e57 100644 --- a/sprout/tuple/tuple_comparison.hpp +++ b/sprout/tuple/tuple_comparison.hpp @@ -46,7 +46,7 @@ namespace sprout { }; } // namespace detail template - bool SPROUT_CONSTEXPR inline operator==( + SPROUT_CONSTEXPR inline bool operator==( sprout::tuples::tuple const& lhs, sprout::tuples::tuple const& rhs ) @@ -62,7 +62,7 @@ namespace sprout { >::eq(lhs, rhs); } template - bool SPROUT_CONSTEXPR inline operator<( + SPROUT_CONSTEXPR inline bool operator<( sprout::tuples::tuple const& lhs, sprout::tuples::tuple const& rhs ) @@ -78,7 +78,7 @@ namespace sprout { >::less(lhs, rhs); } template - bool SPROUT_CONSTEXPR inline operator!=( + SPROUT_CONSTEXPR inline bool operator!=( sprout::tuples::tuple const& lhs, sprout::tuples::tuple const& rhs ) @@ -86,7 +86,7 @@ namespace sprout { return !(lhs == rhs); } template - bool SPROUT_CONSTEXPR inline operator>( + SPROUT_CONSTEXPR inline bool operator>( sprout::tuples::tuple const& lhs, sprout::tuples::tuple const& rhs ) @@ -94,7 +94,7 @@ namespace sprout { return rhs < lhs; } template - bool SPROUT_CONSTEXPR inline operator<=( + SPROUT_CONSTEXPR inline bool operator<=( sprout::tuples::tuple const& lhs, sprout::tuples::tuple const& rhs ) @@ -102,7 +102,7 @@ namespace sprout { return !(rhs < lhs); } template - bool SPROUT_CONSTEXPR inline operator>=( + SPROUT_CONSTEXPR inline bool operator>=( sprout::tuples::tuple const& lhs, sprout::tuples::tuple const& rhs ) diff --git a/sprout/type.hpp b/sprout/type.hpp new file mode 100644 index 00000000..34e2206a --- /dev/null +++ b/sprout/type.hpp @@ -0,0 +1,11 @@ +#ifndef SPROUT_TYPE_HPP +#define SPROUT_TYPE_HPP + +#include +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_TYPE_HPP diff --git a/sprout/type/algorithm.hpp b/sprout/type/algorithm.hpp new file mode 100644 index 00000000..8a816908 --- /dev/null +++ b/sprout/type/algorithm.hpp @@ -0,0 +1,7 @@ +#ifndef SPROUT_TYPE_ALGORITHM_HPP +#define SPROUT_TYPE_ALGORITHM_HPP + +#include +#include + +#endif // #ifndef SPROUT_TYPE_ALGORITHM_HPP diff --git a/sprout/type/algorithm/find_index.hpp b/sprout/type/algorithm/find_index.hpp new file mode 100644 index 00000000..0b925d0f --- /dev/null +++ b/sprout/type/algorithm/find_index.hpp @@ -0,0 +1,49 @@ +#ifndef SPROUT_TYPE_ALGORITHM_FIND_INDEX_HPP +#define SPROUT_TYPE_ALGORITHM_FIND_INDEX_HPP + +#include +#include +#include +#include + +namespace sprout { + namespace types { + namespace detail { + template + struct find_index_impl; + template + struct find_index_impl< + Tuple, + T, + I, + typename std::enable_if< + I == sprout::types::tuple_size::value + || std::is_same::type, T>::value + >::type + > + : public std::integral_constant + {}; + template + struct find_index_impl< + Tuple, + T, + I, + typename std::enable_if< + I != sprout::types::tuple_size::value + && !std::is_same::type, T>::value + >::type + > + : public sprout::types::detail::find_index_impl + {}; + } // namespace detail + // + // find_index + // + template + struct find_index + : public sprout::types::detail::find_index_impl + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_ALGORITHM_FIND_INDEX_HPP diff --git a/sprout/type/iterator.hpp b/sprout/type/iterator.hpp new file mode 100644 index 00000000..fd7f2f7f --- /dev/null +++ b/sprout/type/iterator.hpp @@ -0,0 +1,9 @@ +#ifndef SPROUT_TYPE_ITERATOR_HPP +#define SPROUT_TYPE_ITERATOR_HPP + +#include +#include +#include +#include + +#endif // #ifndef SPROUT_TYPE_ITERATOR_HPP diff --git a/sprout/type/iterator/deref.hpp b/sprout/type/iterator/deref.hpp new file mode 100644 index 00000000..7c1f139b --- /dev/null +++ b/sprout/type/iterator/deref.hpp @@ -0,0 +1,19 @@ +#ifndef SPROUT_TYPE_ITERATOR_DEREF_HPP +#define SPROUT_TYPE_ITERATOR_DEREF_HPP + +#include + +namespace sprout { + namespace types { + // + // deref + // + template + struct deref { + public: + typedef typename Iterator::type type; + }; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_ITERATOR_DEREF_HPP diff --git a/sprout/type/iterator/index_iterator.hpp b/sprout/type/iterator/index_iterator.hpp new file mode 100644 index 00000000..70252b34 --- /dev/null +++ b/sprout/type/iterator/index_iterator.hpp @@ -0,0 +1,91 @@ +#ifndef SPROUT_TYPE_ITERATOR_INDEX_ITERATOR_HPP +#define SPROUT_TYPE_ITERATOR_INDEX_ITERATOR_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + template + struct index_iterator; + + namespace detail { + // + // index_iterator_impl + // + template + struct index_iterator_impl; + template + struct index_iterator_impl< + Tuple, + Index, + typename std::enable_if< + sprout::types::tuple_size::value == 0 + || (Index < 0) + || (Index > sprout::types::tuple_size::value) + >::type + > { + public: + typedef sprout::types::void_ type; + typedef sprout::types::void_ next; + typedef sprout::types::void_ prev; + }; + template + struct index_iterator_impl< + Tuple, + Index, + typename std::enable_if< + sprout::types::tuple_size::value != 0 + && Index == 0 + >::type + > { + public: + typedef typename sprout::types::tuple_element::type type; + typedef sprout::types::index_iterator next; + typedef sprout::types::void_ prev; + }; + template + struct index_iterator_impl< + Tuple, + Index, + typename std::enable_if< + sprout::types::tuple_size::value != 0 + && Index == sprout::types::tuple_size::value + >::type + > { + public: + typedef sprout::types::void_ type; + typedef sprout::types::void_ next; + typedef sprout::types::index_iterator::value - 1> prev; + }; + template + struct index_iterator_impl< + Tuple, + Index, + typename std::enable_if< + sprout::types::tuple_size::value != 0 + && (Index > 0) + && (Index < sprout::types::tuple_size::value) + >::type + > { + public: + typedef typename sprout::types::tuple_element::type type; + typedef sprout::types::index_iterator next; + typedef sprout::types::index_iterator prev; + }; + } // namespace detail + // + // index_iterator + // + template + struct index_iterator + : public sprout::types::detail::index_iterator_impl + , public std::integral_constant + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_ITERATOR_INDEX_ITERATOR_HPP diff --git a/sprout/type/iterator/next.hpp b/sprout/type/iterator/next.hpp new file mode 100644 index 00000000..bcc969b0 --- /dev/null +++ b/sprout/type/iterator/next.hpp @@ -0,0 +1,19 @@ +#ifndef SPROUT_TYPE_ITERATOR_NEXT_HPP +#define SPROUT_TYPE_ITERATOR_NEXT_HPP + +#include + +namespace sprout { + namespace types { + // + // next + // + template + struct next { + public: + typedef typename Iterator::next type; + }; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_ITERATOR_NEXT_HPP diff --git a/sprout/type/iterator/prev.hpp b/sprout/type/iterator/prev.hpp new file mode 100644 index 00000000..8ed91cb2 --- /dev/null +++ b/sprout/type/iterator/prev.hpp @@ -0,0 +1,19 @@ +#ifndef SPROUT_TYPE_ITERATOR_PREV_HPP +#define SPROUT_TYPE_ITERATOR_PREV_HPP + +#include + +namespace sprout { + namespace types { + // + // prev + // + template + struct prev { + public: + typedef typename Iterator::prev type; + }; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_ITERATOR_PREV_HPP diff --git a/sprout/type/operation.hpp b/sprout/type/operation.hpp new file mode 100644 index 00000000..387e3e5c --- /dev/null +++ b/sprout/type/operation.hpp @@ -0,0 +1,10 @@ +#ifndef SPROUT_TYPE_OPERATION_HPP +#define SPROUT_TYPE_OPERATION_HPP + +#include +#include +#include +#include +#include + +#endif // #ifndef SPROUT_TYPE_OPERATION_HPP diff --git a/sprout/type/operation/append_back.hpp b/sprout/type/operation/append_back.hpp new file mode 100644 index 00000000..eacb67f2 --- /dev/null +++ b/sprout/type/operation/append_back.hpp @@ -0,0 +1,38 @@ +#ifndef SPROUT_TYPE_OPERATION_APPEND_BACK_HPP +#define SPROUT_TYPE_OPERATION_APPEND_BACK_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // append_back + // + template + struct append_back { + private: + template + struct apply_impl; + template + struct apply_impl, sprout::index_tuple > + : public sprout::types::rebind_types< + Tuple + >::template apply< + typename sprout::types::tuple_element::type..., + typename sprout::types::tuple_element::type... + > + {}; + public: + typedef typename apply_impl< + typename sprout::index_range<0, sprout::types::tuple_size::value>::type, + typename sprout::index_range<0, sprout::types::tuple_size::value>::type + >::type type; + }; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_OPERATION_APPEND_BACK_HPP diff --git a/sprout/type/operation/append_front.hpp b/sprout/type/operation/append_front.hpp new file mode 100644 index 00000000..a59d0607 --- /dev/null +++ b/sprout/type/operation/append_front.hpp @@ -0,0 +1,38 @@ +#ifndef SPROUT_TYPE_OPERATION_APPEND_FRONT_HPP +#define SPROUT_TYPE_OPERATION_APPEND_FRONT_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // append_front + // + template + struct append_front { + private: + template + struct apply_impl; + template + struct apply_impl, sprout::index_tuple > + : public sprout::types::rebind_types< + Tuple + >::template apply< + typename sprout::types::tuple_element::type..., + typename sprout::types::tuple_element::type... + > + {}; + public: + typedef typename apply_impl< + typename sprout::index_range<0, sprout::types::tuple_size::value>::type, + typename sprout::index_range<0, sprout::types::tuple_size::value>::type + >::type type; + }; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_OPERATION_APPEND_FRONT_HPP diff --git a/sprout/type/operation/push_back.hpp b/sprout/type/operation/push_back.hpp new file mode 100644 index 00000000..78e3ebba --- /dev/null +++ b/sprout/type/operation/push_back.hpp @@ -0,0 +1,37 @@ +#ifndef SPROUT_TYPE_OPERATION_PUSH_BACK_HPP +#define SPROUT_TYPE_OPERATION_PUSH_BACK_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // push_back + // + template + struct push_back { + private: + template + struct apply_impl; + template + struct apply_impl > + : public sprout::types::rebind_types< + Tuple + >::template apply< + typename sprout::types::tuple_element::type..., + T + > + {}; + public: + typedef typename apply_impl< + typename sprout::index_range<0, sprout::types::tuple_size::value>::type + >::type type; + }; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_OPERATION_PUSH_BACK_HPP diff --git a/sprout/type/operation/push_front.hpp b/sprout/type/operation/push_front.hpp new file mode 100644 index 00000000..5e9ef938 --- /dev/null +++ b/sprout/type/operation/push_front.hpp @@ -0,0 +1,37 @@ +#ifndef SPROUT_TYPE_OPERATION_PUSH_FRONT_HPP +#define SPROUT_TYPE_OPERATION_PUSH_FRONT_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // push_front + // + template + struct push_front { + private: + template + struct apply_impl; + template + struct apply_impl > + : public sprout::types::rebind_types< + Tuple + >::template apply< + T, + typename sprout::types::tuple_element::type... + > + {}; + public: + typedef typename apply_impl< + typename sprout::index_range<0, sprout::types::tuple_size::value>::type + >::type type; + }; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_OPERATION_PUSH_FRONT_HPP diff --git a/sprout/type/rebind_types.hpp b/sprout/type/rebind_types.hpp new file mode 100644 index 00000000..e44e69ef --- /dev/null +++ b/sprout/type/rebind_types.hpp @@ -0,0 +1,29 @@ +#ifndef SPROUT_TYPE_REBIND_TYPES_HPP +#define SPROUT_TYPE_REBIND_TYPES_HPP + +#include +#include + +namespace sprout { + namespace types { + // + // rebind_types + // + template + struct rebind_types; + + template + struct rebind_types > { + public: + template + struct apply { + public: + typedef sprout::types::type_tuple type; + }; + }; + } // namespace types + + using sprout::types::rebind_types; +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_REBIND_TYPES_HPP diff --git a/sprout/type/seq/algorithm.hpp b/sprout/type/seq/algorithm.hpp new file mode 100644 index 00000000..fd3fd892 --- /dev/null +++ b/sprout/type/seq/algorithm.hpp @@ -0,0 +1,7 @@ +#ifndef SPROUT_TYPE_SEQ_ALGORITHM_HPP +#define SPROUT_TYPE_SEQ_ALGORITHM_HPP + +#include +#include + +#endif // #ifndef SPROUT_TYPE_SEQ_ALGORITHM_HPP diff --git a/sprout/type/seq/algorithm/find.hpp b/sprout/type/seq/algorithm/find.hpp new file mode 100644 index 00000000..89195fc7 --- /dev/null +++ b/sprout/type/seq/algorithm/find.hpp @@ -0,0 +1,71 @@ +#ifndef SPROUT_TYPE_SEQ_ALGORITHM_FIND_HPP +#define SPROUT_TYPE_SEQ_ALGORITHM_FIND_HPP + +#include +#include +#include + +namespace sprout { + namespace types { + namespace seq { + namespace detail { + template + struct find_impl; + template + struct find_impl< + First, + Last, + T, + typename std::enable_if< + std::is_same::value + >::type + > { + public: + typedef Last type; + }; + template + struct find_impl< + First, + Last, + T, + typename std::enable_if< + !std::is_same::value + && std::is_same::type, T>::value + >::type + > { + public: + typedef First type; + }; + template + struct find_impl< + First, + Last, + T, + typename std::enable_if< + !std::is_same::value + && !std::is_same::type, T>::value + >::type + > + : public sprout::types::seq::detail::find_impl< + typename sprout::types::next::type, + Last, + T + > + {}; + } // namespace detail + // + // find + // + template + struct find + : public sprout::types::seq::detail::find_impl< + typename sprout::types::begin::type, + typename sprout::types::end::type, + T + > + {}; + } // namespace seq + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_SEQ_ALGORITHM_FIND_HPP diff --git a/sprout/type/tuple.hpp b/sprout/type/tuple.hpp new file mode 100644 index 00000000..c3cbd29f --- /dev/null +++ b/sprout/type/tuple.hpp @@ -0,0 +1,42 @@ +#ifndef SPROUT_TYPE_TUPLE_HPP +#define SPROUT_TYPE_TUPLE_HPP + +#include +#include +#include + +namespace sprout { + namespace types { + // + // begin + // + template + struct begin { + typedef typename T::begin type; + }; + // + // end + // + template + struct end { + typedef typename T::end type; + }; + + // + // tuple_size + // + template + struct tuple_size + : public std::tuple_size + {}; + // + // tuple_element + // + template + struct tuple_element + : public std::tuple_element + {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_TUPLE_HPP diff --git a/sprout/type/type_tuple.hpp b/sprout/type/type_tuple.hpp new file mode 100644 index 00000000..9ddafdb5 --- /dev/null +++ b/sprout/type/type_tuple.hpp @@ -0,0 +1,60 @@ +#ifndef SPROUT_TYPE_TYPE_TUPLE_HPP +#define SPROUT_TYPE_TYPE_TUPLE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace types { + // + // type_tuple + // + template + struct type_tuple { + public: + typedef sprout::types::index_iterator begin; + typedef sprout::types::index_iterator end; + }; + + namespace detail { + template + struct tuple_element_impl; + template + struct tuple_element_impl<0, sprout::types::type_tuple > { + public: + typedef Head type; + }; + template + struct tuple_element_impl > + : public sprout::types::detail::tuple_element_impl > + {}; + } // namespace detail + } // namespace types + + using sprout::types::type_tuple; +} // namespace sprout + +namespace std { + // + // tuple_size + // + template + struct tuple_size > + : public std::integral_constant + {}; + + // + // tuple_element + // + template + struct tuple_element > + : public sprout::types::detail::tuple_element_impl > + {}; +} // namespace std + +#endif // #ifndef SPROUT_TYPE_TYPE_TUPLE_HPP diff --git a/sprout/type/void.hpp b/sprout/type/void.hpp new file mode 100644 index 00000000..1e3f60a1 --- /dev/null +++ b/sprout/type/void.hpp @@ -0,0 +1,15 @@ +#ifndef SPROUT_TYPE_VOID_HPP +#define SPROUT_TYPE_VOID_HPP + +#include + +namespace sprout { + namespace types { + // + // void_ + // + struct void_ {}; + } // namespace types +} // namespace sprout + +#endif // #ifndef SPROUT_TYPE_VOID_HPP diff --git a/sprout/variant.hpp b/sprout/variant.hpp new file mode 100644 index 00000000..c9c77ab2 --- /dev/null +++ b/sprout/variant.hpp @@ -0,0 +1,8 @@ +#ifndef SPROUT_VARIANT_HPP +#define SPROUT_VARIANT_HPP + +#include +#include +#include + +#endif // #ifndef SPROUT_VARIANT_HPP diff --git a/sprout/variant/get.hpp b/sprout/variant/get.hpp new file mode 100644 index 00000000..99e34800 --- /dev/null +++ b/sprout/variant/get.hpp @@ -0,0 +1,21 @@ +#ifndef SPROUT_VARIANT_GET_HPP +#define SPROUT_VARIANT_GET_HPP + +#include +#include + +namespace sprout { + // + // get + // + template + SPROUT_CONSTEXPR U const& get(sprout::variant const& operand) { + return operand.template get(); + } + template + U& get(sprout::variant& operand) { + return operand.template get(); + } +} // namespace sprout + +#endif // #ifndef SPROUT_VARIANT_GET_HPP diff --git a/sprout/variant/variant.hpp b/sprout/variant/variant.hpp new file mode 100644 index 00000000..3439b47c --- /dev/null +++ b/sprout/variant/variant.hpp @@ -0,0 +1,233 @@ +#ifndef SPROUT_VARIANT_VARIANT_HPP +#define SPROUT_VARIANT_VARIANT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + class variant_impl { + protected: + typedef sprout::tuples::tuple tuple_type;; + private: + template + static SPROUT_CONSTEXPR tuple_type init(T&& operand, sprout::index_tuple) { + return sprout::tuples::make_clone( + typename sprout::tuples::tuple_element::type()..., + sprout::forward(operand) + ); + } + protected: + tuple_type tuple_; + int which_; + protected: + SPROUT_CONSTEXPR variant_impl() + : tuple_() + , which_() + {} + template + SPROUT_CONSTEXPR variant_impl(T&& operand, Index) + : tuple_(init(sprout::forward(operand), typename sprout::index_range<0, Index::value>::type())) + , which_(Index::value) + { + static_assert(Index::value < sizeof...(Types), "variant<>: invalid operand"); + } + void swap(variant_impl& other) SPROUT_NOEXCEPT_EXPR( + SPROUT_NOEXCEPT_EXPR(swap(std::declval(), std::declval())) + ) + { + using std::swap; + swap(tuple_, other.tuple_); + swap(which_, other.which_); + } + variant_impl& operator=(variant_impl const&) = default; + }; + } // namespace detail + // + // variant + // + template + class variant + : private sprout::detail::variant_impl + { + private: + typedef sprout::detail::variant_impl impl_type;; + public: + typedef typename impl_type::tuple_type tuple_type;; + private: + template + static SPROUT_CONSTEXPR typename std::enable_if< + I == sizeof...(Types), + bool + >::type eq(tuple_type const& l, tuple_type const& r, int which) { + return false; + } + template + static SPROUT_CONSTEXPR typename std::enable_if< + I != sizeof...(Types), + bool + >::type eq(tuple_type const& l, tuple_type const& r, int which) { + return I == which + ? sprout::tuples::get(l) == sprout::tuples::get(r) + : eq(l, r, which) + ; + } + template + static SPROUT_CONSTEXPR typename std::enable_if< + static_cast(I) == sizeof...(Types), + bool + >::type lt(tuple_type const& l, tuple_type const& r, int which) { + return false; + } + template + static SPROUT_CONSTEXPR typename std::enable_if< + static_cast(I) != sizeof...(Types), + bool + >::type lt(tuple_type const& l, tuple_type const& r, int which) { + return I == which + ? sprout::tuples::get(l) < sprout::tuples::get(r) + : lt(l, r, which) + ; + } + template + static typename std::enable_if< + static_cast(I) == sizeof...(Types), + std::basic_ostream& + >::type output(std::basic_ostream& os, tuple_type const& t, int which) { + return os; + } + template + static typename std::enable_if< + static_cast(I) != sizeof...(Types), + std::basic_ostream& + >::type output(std::basic_ostream& os, tuple_type const& t, int which) { + return I == which + ? os << sprout::tuples::get(t) + : output(os, t, which) + ; + } + private: + using impl_type::tuple_; + using impl_type::which_; + public: + // construct/copy/destruct + SPROUT_CONSTEXPR variant() + : impl_type() + {} + variant(variant const&) = default; + template + SPROUT_CONSTEXPR variant(T&& operand) + : impl_type(sprout::forward(operand), sprout::types::find_index()) + {} + // modifiers + void swap(variant& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(impl_type::swap(other))) { + impl_type::swap(other); + } + variant& operator=(variant const& rhs) { + static_cast(*this) = rhs; + return *this; + } + variant& operator=(variant&& rhs) SPROUT_NOEXCEPT_EXPR(std::is_nothrow_move_assignable::value) { + static_cast(*this) = sprout::move(rhs); + return *this; + } + template + variant& operator=(T&& rhs) { + static_cast(*this) = variant(sprout::forward(rhs)); + return *this; + } + // queries + SPROUT_CONSTEXPR int which() const { + return which_; + } + SPROUT_CONSTEXPR bool empty() const { + return sizeof...(Types) == 0; + } + // relational + friend SPROUT_CONSTEXPR bool operator==(variant const& lhs, variant const& rhs) { + return lhs.which_ == rhs.which_ && eq<0>(lhs.tuple_, rhs.tuple_, lhs.which_); + } + friend SPROUT_CONSTEXPR bool operator!=(variant const& lhs, variant const& rhs) { + return !(lhs == rhs); + } + friend SPROUT_CONSTEXPR bool operator<(variant const& lhs, variant const& rhs) { + return lhs.which_ < rhs.which_ + || (lhs.which_ == rhs.which_ && lt<0>(lhs.tuple_, rhs.tuple_, lhs.which_)) + ; + } + friend SPROUT_CONSTEXPR bool operator>(variant const& lhs, variant const& rhs) { + return rhs < lhs; + } + friend SPROUT_CONSTEXPR bool operator<=(variant const& lhs, variant const& rhs) { + return !(rhs < lhs); + } + friend SPROUT_CONSTEXPR bool operator>=(variant const& lhs, variant const& rhs) { + return !(lhs < rhs); + } + + template + friend std::basic_ostream& operator<<(std::basic_ostream& lhs, variant const& rhs) { + return output<0>(lhs, rhs.tuple_, rhs.which_); + } + template + SPROUT_CONSTEXPR typename std::enable_if< + sprout::types::find_index::value != sizeof...(Types), + U const& + >::type get() const { + return sprout::types::find_index::value == static_cast(which_) + ? sprout::tuples::get::value>(tuple_) + : (throw std::domain_error("variant<>: bad get"), sprout::tuples::get::value>(tuple_)) + ; + } + template + typename std::enable_if< + sprout::types::find_index::value != sizeof...(Types), + U& + >::type get() { + return sprout::types::find_index::value == which_ + ? sprout::tuples::get::value>(tuple_) + : (throw std::domain_error("variant<>: bad get"), sprout::tuples::get::value>(tuple_)) + ; + } + }; + + // + // swap + // + template + inline void swap( + sprout::variant& lhs, + sprout::variant& rhs + ) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) + { + lhs.swap(rhs); + } +} // namespace sprout + +namespace std { + // + // tuple_size + // + template + struct tuple_size > + : public std::tuple_size::tuple_tyep> + {}; + + // + // tuple_element + // + template + struct tuple_element > + : public std::tuple_element::tuple_tyep> + {}; +} // namespace std + +#endif // #ifndef SPROUT_VARIANT_VARIANT_HPP