sprout/variant/variant.hpp 修正

sprout/weed/attr_cnv/bitwise_or.hpp (variant に対応)
This commit is contained in:
bolero-MURAKAMI 2012-01-11 01:34:37 +09:00
parent e731c3caf4
commit e11da4400b
4 changed files with 71 additions and 12 deletions

View file

@ -1,7 +1,9 @@
#ifndef SPROUT_VARIANT_GET_HPP #ifndef SPROUT_VARIANT_GET_HPP
#define SPROUT_VARIANT_GET_HPP #define SPROUT_VARIANT_GET_HPP
#include <cstddef>
#include <sprout/config.hpp> #include <sprout/config.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/variant/variant.hpp> #include <sprout/variant/variant.hpp>
namespace sprout { namespace sprout {
@ -16,6 +18,20 @@ namespace sprout {
U& get(sprout::variant<Types...>& operand) { U& get(sprout::variant<Types...>& operand) {
return operand.template get<U>(); return operand.template get<U>();
} }
template<std::size_t I, typename... Types>
SPROUT_CONSTEXPR typename sprout::tuples::tuple_element<
I,
sprout::variant<Types...>
>::type const& get(sprout::variant<Types...> const& operand) {
return operand.template get_at<I>();
}
template<std::size_t I, typename... Types>
typename sprout::tuples::tuple_element<
I,
sprout::variant<Types...>
>::type& get(sprout::variant<Types...>& operand) {
return operand.template get_at<I>();
}
} // namespace sprout } // namespace sprout
#endif // #ifndef SPROUT_VARIANT_GET_HPP #endif // #ifndef SPROUT_VARIANT_GET_HPP

View file

@ -4,11 +4,13 @@
#include <cstddef> #include <cstddef>
#include <utility> #include <utility>
#include <stdexcept> #include <stdexcept>
#include <type_traits>
#include <sprout/config.hpp> #include <sprout/config.hpp>
#include <sprout/index_tuple.hpp> #include <sprout/index_tuple.hpp>
#include <sprout/utility/operation.hpp> #include <sprout/utility/operation.hpp>
#include <sprout/tuple/tuple.hpp> #include <sprout/tuple/tuple.hpp>
#include <sprout/tuple/functions.hpp> #include <sprout/tuple/functions.hpp>
#include <sprout/type/type_tuple.hpp>
#include <sprout/type/algorithm/find_index.hpp> #include <sprout/type/algorithm/find_index.hpp>
namespace sprout { namespace sprout {
@ -17,6 +19,7 @@ namespace sprout {
class variant_impl { class variant_impl {
protected: protected:
typedef sprout::tuples::tuple<Types...> tuple_type;; typedef sprout::tuples::tuple<Types...> tuple_type;;
typedef sprout::types::type_tuple<typename std::decay<Types>::type...> uncvref_tuple_type;;
private: private:
template<typename T, std::ptrdiff_t... Indexes> template<typename T, std::ptrdiff_t... Indexes>
static SPROUT_CONSTEXPR tuple_type init(T&& operand, sprout::index_tuple<Indexes...>) { static SPROUT_CONSTEXPR tuple_type init(T&& operand, sprout::index_tuple<Indexes...>) {
@ -60,6 +63,7 @@ namespace sprout {
{ {
private: private:
typedef sprout::detail::variant_impl<Types...> impl_type;; typedef sprout::detail::variant_impl<Types...> impl_type;;
typedef typename impl_type::uncvref_tuple_type uncvref_tuple_type;;
public: public:
typedef typename impl_type::tuple_type tuple_type;; typedef typename impl_type::tuple_type tuple_type;;
private: private:
@ -143,7 +147,10 @@ namespace sprout {
variant(variant&&) = default; variant(variant&&) = default;
template<typename T> template<typename T>
SPROUT_CONSTEXPR variant(T&& operand) SPROUT_CONSTEXPR variant(T&& operand)
: impl_type(sprout::forward<T>(operand), sprout::types::find_index<tuple_type, T>()) : impl_type(
sprout::forward<T>(operand),
sprout::types::find_index<uncvref_tuple_type, typename std::decay<T>::type>()
)
{} {}
// modifiers // modifiers
void swap(variant& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(impl_type::swap(other))) { void swap(variant& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(impl_type::swap(other))) {
@ -196,25 +203,39 @@ namespace sprout {
return output<0>(lhs, rhs.tuple_, rhs.which_); return output<0>(lhs, rhs.tuple_, rhs.which_);
} }
// get support // get support
template<std::size_t I>
SPROUT_CONSTEXPR typename std::enable_if<
I != sizeof...(Types),
typename sprout::tuples::tuple_element<I, tuple_type>::type const&
>::type get_at() const {
return I == static_cast<std::size_t>(which_)
? sprout::tuples::get<I>(tuple_)
: (throw std::domain_error("variant<>: bad get"), sprout::tuples::get<I>(tuple_))
;
}
template<std::size_t I>
typename std::enable_if<
I != sizeof...(Types),
typename sprout::tuples::tuple_element<I, tuple_type>::type&
>::type get_at() {
return I == which_
? sprout::tuples::get<I>(tuple_)
: (throw std::domain_error("variant<>: bad get"), sprout::tuples::get<I>(tuple_))
;
}
template<typename U> template<typename U>
SPROUT_CONSTEXPR typename std::enable_if< SPROUT_CONSTEXPR typename std::enable_if<
sprout::types::find_index<tuple_type, U>::value != sizeof...(Types), sprout::types::find_index<tuple_type, U>::value != sizeof...(Types),
U const& U const&
>::type get() const { >::type get() const {
return sprout::types::find_index<tuple_type, U>::value == static_cast<std::size_t>(which_) return get_at<sprout::types::find_index<tuple_type, U>::value>();
? sprout::tuples::get<sprout::types::find_index<tuple_type, U>::value>(tuple_)
: (throw std::domain_error("variant<>: bad get"), sprout::tuples::get<sprout::types::find_index<tuple_type, U>::value>(tuple_))
;
} }
template<typename U> template<typename U>
typename std::enable_if< typename std::enable_if<
sprout::types::find_index<tuple_type, U>::value != sizeof...(Types), sprout::types::find_index<tuple_type, U>::value != sizeof...(Types),
U& U&
>::type get() { >::type get() {
return sprout::types::find_index<tuple_type, U>::value == which_ return get_at<sprout::types::find_index<tuple_type, U>::value>();
? sprout::tuples::get<sprout::types::find_index<tuple_type, U>::value>(tuple_)
: (throw std::domain_error("variant<>: bad get"), sprout::tuples::get<sprout::types::find_index<tuple_type, U>::value>(tuple_))
;
} }
// visitation support // visitation support
template<typename Visitor> template<typename Visitor>
@ -245,9 +266,8 @@ namespace std {
// tuple_size // tuple_size
// //
template<typename... Types> template<typename... Types>
struct tuple_size<sprout::variant<Types...> > struct tuple_size<sprout::variant<Types...> >
: public std::tuple_size<typename sprout::variant<Types...>::tuple_tyep> : public std::tuple_size<typename sprout::variant<Types...>::tuple_type>
{}; {};
// //
@ -255,7 +275,7 @@ namespace std {
// //
template<std::size_t I, typename... Types> template<std::size_t I, typename... Types>
struct tuple_element<I, sprout::variant<Types...> > struct tuple_element<I, sprout::variant<Types...> >
: public std::tuple_element<I, typename sprout::variant<Types...>::tuple_tyep> : public std::tuple_element<I, typename sprout::variant<Types...>::tuple_type>
{}; {};
} // namespace std } // namespace std

View file

@ -13,6 +13,7 @@
#include <sprout/weed/detail/is_elem_and_container.hpp> #include <sprout/weed/detail/is_elem_and_container.hpp>
#include <sprout/weed/detail/is_both_tuple.hpp> #include <sprout/weed/detail/is_both_tuple.hpp>
#include <sprout/weed/detail/is_same_elem.hpp> #include <sprout/weed/detail/is_same_elem.hpp>
#include <sprout/weed/detail/is_different_elem.hpp>
#include <sprout/weed/detail/is_elem_and_unused.hpp> #include <sprout/weed/detail/is_elem_and_unused.hpp>
#include <sprout/weed/detail/is_unused_and_elem.hpp> #include <sprout/weed/detail/is_unused_and_elem.hpp>
#include <sprout/weed/detail/is_both_unused.hpp> #include <sprout/weed/detail/is_both_unused.hpp>
@ -88,6 +89,14 @@ namespace sprout {
>::type bitwise_or(X const& x) { >::type bitwise_or(X const& x) {
return x; return x;
} }
// V | W -> variant<V, W>
template<typename T, typename U, typename X>
SPROUT_CONSTEXPR inline typename std::enable_if<
sprout::weed::detail::is_different_elem<T, U>::value,
typename sprout::weed::attr_cnv::result_of::bitwise_or<T, U>::type
>::type bitwise_or(X const& x) {
return typename sprout::weed::attr_cnv::result_of::bitwise_or<T, U>::type(x);
}
// V | unused -> container<V, 1> // V | unused -> container<V, 1>
template<typename T, typename U, typename X> template<typename T, typename U, typename X>
SPROUT_CONSTEXPR inline typename std::enable_if< SPROUT_CONSTEXPR inline typename std::enable_if<

View file

@ -6,6 +6,7 @@
#include <sprout/string.hpp> #include <sprout/string.hpp>
#include <sprout/array.hpp> #include <sprout/array.hpp>
#include <sprout/tuple/tuple.hpp> #include <sprout/tuple/tuple.hpp>
#include <sprout/variant/variant.hpp>
#include <sprout/weed/unused.hpp> #include <sprout/weed/unused.hpp>
#include <sprout/weed/traits/type/is_char_type.hpp> #include <sprout/weed/traits/type/is_char_type.hpp>
#include <sprout/weed/detail/is_same_container.hpp> #include <sprout/weed/detail/is_same_container.hpp>
@ -13,6 +14,7 @@
#include <sprout/weed/detail/is_elem_and_container.hpp> #include <sprout/weed/detail/is_elem_and_container.hpp>
#include <sprout/weed/detail/is_both_tuple.hpp> #include <sprout/weed/detail/is_both_tuple.hpp>
#include <sprout/weed/detail/is_same_elem.hpp> #include <sprout/weed/detail/is_same_elem.hpp>
#include <sprout/weed/detail/is_different_elem.hpp>
#include <sprout/weed/detail/is_elem_and_unused.hpp> #include <sprout/weed/detail/is_elem_and_unused.hpp>
#include <sprout/weed/detail/is_unused_and_elem.hpp> #include <sprout/weed/detail/is_unused_and_elem.hpp>
#include <sprout/weed/detail/is_both_unused.hpp> #include <sprout/weed/detail/is_both_unused.hpp>
@ -102,6 +104,18 @@ namespace sprout {
public: public:
typedef T type; typedef T type;
}; };
// V | W -> variant<V, W>
template<typename T, typename U>
struct bitwise_or<
T,
U,
typename std::enable_if<
sprout::weed::detail::is_different_elem<T, U>::value
>::type
> {
public:
typedef sprout::variant<T, U> type;
};
// V | unused -> container<V, 1> // V | unused -> container<V, 1>
template<typename T, typename U> template<typename T, typename U>
struct bitwise_or< struct bitwise_or<