stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
@file
|
||||
Defines `boost::hana::experimental::print`.
|
||||
|
||||
@copyright Louis Dionne 2013-2017
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
|
||||
#define BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
|
||||
|
||||
#include <boost/hana/concept/constant.hpp>
|
||||
#include <boost/hana/concept/product.hpp>
|
||||
#include <boost/hana/concept/sequence.hpp>
|
||||
#include <boost/hana/config.hpp>
|
||||
#include <boost/hana/core/to.hpp>
|
||||
#include <boost/hana/core/dispatch.hpp>
|
||||
#include <boost/hana/first.hpp>
|
||||
#include <boost/hana/for_each.hpp>
|
||||
#include <boost/hana/intersperse.hpp>
|
||||
#include <boost/hana/second.hpp>
|
||||
#include <boost/hana/transform.hpp>
|
||||
#include <boost/hana/tuple.hpp>
|
||||
|
||||
// models for different containers
|
||||
#include <boost/hana/fwd/map.hpp>
|
||||
#include <boost/hana/fwd/optional.hpp>
|
||||
#include <boost/hana/fwd/set.hpp>
|
||||
#include <boost/hana/fwd/string.hpp>
|
||||
#include <boost/hana/fwd/type.hpp>
|
||||
|
||||
#include <boost/core/demangle.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
|
||||
BOOST_HANA_NAMESPACE_BEGIN namespace experimental {
|
||||
template <typename T>
|
||||
struct Printable;
|
||||
|
||||
//! @cond
|
||||
template <typename T, typename = void>
|
||||
struct print_impl : print_impl<T, hana::when<true>> { };
|
||||
|
||||
template <typename T, bool condition>
|
||||
struct print_impl<T, hana::when<condition>> : hana::default_ {
|
||||
template <typename ...Args>
|
||||
static constexpr auto apply(Args&& ...) = delete;
|
||||
};
|
||||
//! @endcond
|
||||
|
||||
//! @ingroup group-experimental
|
||||
//! Returns a string representation of the given object.
|
||||
//!
|
||||
//! This function is defined for most containers provided by Hana, and
|
||||
//! also for objects that define an `operator<<` that can be used with
|
||||
//! a `std::basic_ostream`. It can recursively print containers within
|
||||
//! containers, but do not expect any kind of proper indentation.
|
||||
//!
|
||||
//! This function requires (the rest of) Boost to be available on the
|
||||
//! system. It also requires RTTI to be enabled.
|
||||
#ifdef BOOST_HANA_DOXYGEN_INVOKED
|
||||
auto print = [](auto const& x) -> std::string {
|
||||
return tag-dispatched;
|
||||
};
|
||||
#else
|
||||
struct print_t {
|
||||
template <typename T>
|
||||
std::string operator()(T const& t) const {
|
||||
using Tag = typename hana::tag_of<T>::type;
|
||||
using Print = BOOST_HANA_DISPATCH_IF(print_impl<Tag>,
|
||||
hana::experimental::Printable<Tag>::value
|
||||
);
|
||||
|
||||
#ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
|
||||
static_assert(hana::experimental::Printable<Tag>::value,
|
||||
"hana::experimental::print(t) requires 't' to be Printable");
|
||||
#endif
|
||||
|
||||
return Print::apply(t);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr print_t print{};
|
||||
#endif
|
||||
|
||||
// Define the `Printable` concept
|
||||
template <typename T>
|
||||
struct Printable {
|
||||
using Tag = typename hana::tag_of<T>::type;
|
||||
static constexpr bool value = !hana::is_default<print_impl<Tag>>::value;
|
||||
};
|
||||
|
||||
namespace print_detail {
|
||||
std::string strip_type_junk(std::string const& str) {
|
||||
return std::regex_replace(str, std::regex("^([a-z_]+::)*([a-z_]*)_t<"), "$2<");
|
||||
}
|
||||
}
|
||||
|
||||
// model for Sequences
|
||||
template <typename S>
|
||||
struct print_impl<S, hana::when<hana::Sequence<S>::value>> {
|
||||
template <typename Xs>
|
||||
static std::string apply(Xs const& xs) {
|
||||
std::string result = "(";
|
||||
auto comma_separated = hana::intersperse(xs, ", ");
|
||||
hana::for_each(comma_separated, [&result](auto const& x) {
|
||||
result += hana::experimental::print(x);
|
||||
});
|
||||
result += ")";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// model for OutputStreamable types
|
||||
//! @cond
|
||||
template <typename S>
|
||||
struct print_impl<S, hana::when_valid<decltype(
|
||||
std::declval<std::ostringstream&>() << std::declval<S const&>()
|
||||
)>> {
|
||||
template <typename T>
|
||||
static std::string apply(T const& t) {
|
||||
std::ostringstream os;
|
||||
os << t;
|
||||
return os.str();
|
||||
}
|
||||
};
|
||||
//! @endcond
|
||||
|
||||
// model for hana::optional
|
||||
template <>
|
||||
struct print_impl<hana::optional_tag> {
|
||||
template <typename O>
|
||||
static std::string apply(O const& optional) {
|
||||
return hana::maybe("nothing",
|
||||
[](auto const& x) {
|
||||
return "just(" + hana::experimental::print(x) + ")";
|
||||
}, optional);
|
||||
}
|
||||
};
|
||||
|
||||
// model for hana::maps
|
||||
template <>
|
||||
struct print_impl<hana::map_tag> {
|
||||
template <typename M>
|
||||
static std::string apply(M const& map) {
|
||||
std::string result = "{";
|
||||
auto pairs = hana::transform(hana::to_tuple(map),
|
||||
[](auto const& pair) {
|
||||
return hana::experimental::print(hana::first(pair))
|
||||
+ " => "
|
||||
+ hana::experimental::print(hana::second(pair));
|
||||
});
|
||||
auto comma_separated = hana::intersperse(pairs, ", ");
|
||||
hana::for_each(comma_separated, [&result](auto const& element) {
|
||||
result += element;
|
||||
});
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// model for hana::metafunctions
|
||||
template <template <typename ...> class F>
|
||||
struct print_impl<hana::metafunction_t<F>> {
|
||||
template <typename T>
|
||||
static std::string apply(T const&) {
|
||||
return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
|
||||
}
|
||||
};
|
||||
|
||||
// model for hana::metafunction_classes
|
||||
template <typename F>
|
||||
struct print_impl<hana::metafunction_class_t<F>> {
|
||||
template <typename T>
|
||||
static std::string apply(T const&) {
|
||||
return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
|
||||
}
|
||||
};
|
||||
|
||||
// model for Constants holding a `Printable`
|
||||
template <typename C>
|
||||
struct print_impl<C, hana::when<
|
||||
hana::Constant<C>::value &&
|
||||
Printable<typename C::value_type>::value
|
||||
>> {
|
||||
template <typename T>
|
||||
static std::string apply(T const&) {
|
||||
constexpr auto value = hana::value<T>();
|
||||
return hana::experimental::print(value);
|
||||
}
|
||||
};
|
||||
|
||||
// model for Products
|
||||
template <typename P>
|
||||
struct print_impl<P, hana::when<hana::Product<P>::value>> {
|
||||
template <typename T>
|
||||
static std::string apply(T const& t) {
|
||||
return '(' + hana::experimental::print(hana::first(t))
|
||||
+ ", "
|
||||
+ hana::experimental::print(hana::second(t)) + ')';
|
||||
}
|
||||
};
|
||||
|
||||
// model for hana::strings
|
||||
template <>
|
||||
struct print_impl<hana::string_tag> {
|
||||
template <typename S>
|
||||
static std::string apply(S const& s) {
|
||||
return '"' + std::string{hana::to<char const*>(s)} + '"';
|
||||
}
|
||||
};
|
||||
|
||||
// model for hana::sets
|
||||
template <>
|
||||
struct print_impl<hana::set_tag> {
|
||||
template <typename S>
|
||||
static std::string apply(S const& set) {
|
||||
std::string result = "{";
|
||||
auto as_tuple = hana::transform(hana::to_tuple(set),
|
||||
hana::experimental::print);
|
||||
auto comma_separated = hana::intersperse(as_tuple, ", ");
|
||||
hana::for_each(comma_separated, [&result](auto const& element) {
|
||||
result += element;
|
||||
});
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// model for hana::templates
|
||||
template <template <typename ...> class F>
|
||||
struct print_impl<template_t<F>> {
|
||||
template <typename T>
|
||||
static std::string apply(T const&) {
|
||||
return print_detail::strip_type_junk(boost::core::demangle(typeid(T).name()));
|
||||
}
|
||||
};
|
||||
|
||||
// model for hana::types
|
||||
template <>
|
||||
struct print_impl<hana::type_tag> {
|
||||
template <typename T>
|
||||
static std::string apply(T const&) {
|
||||
using Type = typename T::type;
|
||||
return "type<" + boost::core::demangle(typeid(Type).name()) + '>';
|
||||
}
|
||||
};
|
||||
} BOOST_HANA_NAMESPACE_END
|
||||
|
||||
#endif // !BOOST_HANA_EXPERIMENTAL_PRINTABLE_HPP
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
@file
|
||||
Defines `boost::hana::experimental::type_name`.
|
||||
|
||||
@copyright Louis Dionne 2013-2017
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_HANA_EXPERIMENTAL_TYPE_NAME_HPP
|
||||
#define BOOST_HANA_EXPERIMENTAL_TYPE_NAME_HPP
|
||||
|
||||
#include <boost/hana/config.hpp>
|
||||
#include <boost/hana/string.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
|
||||
BOOST_HANA_NAMESPACE_BEGIN namespace experimental {
|
||||
namespace detail {
|
||||
struct cstring {
|
||||
char const* ptr;
|
||||
std::size_t length;
|
||||
};
|
||||
|
||||
// Note: We substract the null terminator from the string sizes below.
|
||||
template <typename T>
|
||||
constexpr cstring type_name_impl2() {
|
||||
|
||||
#if defined(__clang__)
|
||||
constexpr char const* pretty_function = __PRETTY_FUNCTION__;
|
||||
constexpr std::size_t total_size = sizeof(__PRETTY_FUNCTION__) - 1;
|
||||
constexpr std::size_t prefix_size = sizeof("boost::hana::experimental::detail::cstring boost::hana::experimental::detail::type_name_impl2() [T = ") - 1;
|
||||
constexpr std::size_t suffix_size = sizeof("]") - 1;
|
||||
#else
|
||||
#error "No support for this compiler."
|
||||
#endif
|
||||
|
||||
return {pretty_function + prefix_size, total_size - prefix_size - suffix_size};
|
||||
}
|
||||
|
||||
template <typename T, std::size_t ...i>
|
||||
auto type_name_impl1(std::index_sequence<i...>) {
|
||||
constexpr auto name = detail::type_name_impl2<T>();
|
||||
return hana::string<*(name.ptr + i)...>{};
|
||||
}
|
||||
} // end namespace detail
|
||||
|
||||
//! @ingroup group-experimental
|
||||
//! Returns a `hana::string` representing the name of the given type, at
|
||||
//! compile-time.
|
||||
//!
|
||||
//! This only works on Clang (and apparently MSVC, but Hana does not work
|
||||
//! there as of writing this). Original idea taken from
|
||||
//! https://github.com/Manu343726/ctti.
|
||||
template <typename T>
|
||||
auto type_name() {
|
||||
constexpr auto name = detail::type_name_impl2<T>();
|
||||
return detail::type_name_impl1<T>(std::make_index_sequence<name.length>{});
|
||||
}
|
||||
} BOOST_HANA_NAMESPACE_END
|
||||
|
||||
#endif // !BOOST_HANA_EXPERIMENTAL_TYPE_NAME_HPP
|
||||
@@ -0,0 +1,158 @@
|
||||
/*!
|
||||
@file
|
||||
Defines `boost::hana::experimental::types`.
|
||||
|
||||
@copyright Louis Dionne 2013-2017
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_HANA_EXPERIMENTAL_TYPES_HPP
|
||||
#define BOOST_HANA_EXPERIMENTAL_TYPES_HPP
|
||||
|
||||
#include <boost/hana/bool.hpp>
|
||||
#include <boost/hana/concept/metafunction.hpp>
|
||||
#include <boost/hana/config.hpp>
|
||||
#include <boost/hana/detail/any_of.hpp>
|
||||
#include <boost/hana/detail/type_at.hpp>
|
||||
#include <boost/hana/fwd/at.hpp>
|
||||
#include <boost/hana/fwd/contains.hpp>
|
||||
#include <boost/hana/fwd/core/tag_of.hpp>
|
||||
#include <boost/hana/fwd/equal.hpp>
|
||||
#include <boost/hana/fwd/is_empty.hpp>
|
||||
#include <boost/hana/fwd/transform.hpp>
|
||||
#include <boost/hana/fwd/unpack.hpp>
|
||||
#include <boost/hana/type.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
|
||||
BOOST_HANA_NAMESPACE_BEGIN
|
||||
namespace experimental {
|
||||
//! @ingroup group-experimental
|
||||
//! Container optimized for holding types.
|
||||
//!
|
||||
//! It is often useful to manipulate a sequence that contains types
|
||||
//! only, without any associated runtime value. This container allows
|
||||
//! storing and manipulating pure types in a much more compile-time
|
||||
//! efficient manner than using `hana::tuple`, which must assume that
|
||||
//! its contents might have runtime values.
|
||||
template <typename ...T>
|
||||
struct types;
|
||||
|
||||
struct types_tag;
|
||||
|
||||
template <typename ...T>
|
||||
struct types { };
|
||||
} // end namespace experimental
|
||||
|
||||
template <typename ...T>
|
||||
struct tag_of<experimental::types<T...>> {
|
||||
using type = experimental::types_tag;
|
||||
};
|
||||
|
||||
// Foldable
|
||||
template <>
|
||||
struct unpack_impl<hana::experimental::types_tag> {
|
||||
template <typename ...T, typename F, typename = typename std::enable_if<
|
||||
!hana::Metafunction<F>::value
|
||||
>::type>
|
||||
static constexpr decltype(auto) apply(hana::experimental::types<T...> const&, F&& f) {
|
||||
return static_cast<F&&>(f)(hana::type<T>{}...);
|
||||
}
|
||||
|
||||
template <typename ...T, typename F, typename = typename std::enable_if<
|
||||
hana::Metafunction<F>::value
|
||||
>::type>
|
||||
static constexpr hana::type<typename F::template apply<T...>::type>
|
||||
apply(hana::experimental::types<T...> const&, F const&) { return {}; }
|
||||
};
|
||||
|
||||
// Functor
|
||||
template <>
|
||||
struct transform_impl<hana::experimental::types_tag> {
|
||||
template <typename ...T, typename F, typename = typename std::enable_if<
|
||||
!hana::Metafunction<F>::value
|
||||
>::type>
|
||||
static constexpr auto apply(hana::experimental::types<T...> const&, F&& f)
|
||||
-> hana::experimental::types<typename decltype(+f(hana::type<T>{}))::type...>
|
||||
{ return {}; }
|
||||
|
||||
template <typename ...T, typename F, typename = typename std::enable_if<
|
||||
hana::Metafunction<F>::value
|
||||
>::type>
|
||||
static constexpr hana::experimental::types<typename F::template apply<T>::type...>
|
||||
apply(hana::experimental::types<T...> const&, F const&) { return {}; }
|
||||
};
|
||||
|
||||
// Iterable
|
||||
template <>
|
||||
struct at_impl<hana::experimental::types_tag> {
|
||||
template <typename ...T, typename N>
|
||||
static constexpr auto
|
||||
apply(hana::experimental::types<T...> const&, N const&) {
|
||||
using Nth = typename detail::type_at<N::value, T...>::type;
|
||||
return hana::type<Nth>{};
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_empty_impl<hana::experimental::types_tag> {
|
||||
template <typename ...T>
|
||||
static constexpr hana::bool_<sizeof...(T) == 0>
|
||||
apply(hana::experimental::types<T...> const&)
|
||||
{ return {}; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct drop_front_impl<hana::experimental::types_tag> {
|
||||
template <std::size_t n, typename ...T, std::size_t ...i>
|
||||
static hana::experimental::types<typename detail::type_at<i + n, T...>::type...>
|
||||
helper(std::index_sequence<i...>);
|
||||
|
||||
template <typename ...T, typename N>
|
||||
static constexpr auto
|
||||
apply(hana::experimental::types<T...> const&, N const&) {
|
||||
constexpr std::size_t n = N::value > sizeof...(T) ? sizeof...(T) : N::value;
|
||||
using Indices = std::make_index_sequence<sizeof...(T) - n>;
|
||||
return decltype(helper<n, T...>(Indices{})){};
|
||||
}
|
||||
};
|
||||
|
||||
// Searchable
|
||||
template <>
|
||||
struct contains_impl<hana::experimental::types_tag> {
|
||||
template <typename U>
|
||||
struct is_same_as {
|
||||
template <typename T>
|
||||
struct apply {
|
||||
static constexpr bool value = std::is_same<U, T>::value;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename ...T, typename U>
|
||||
static constexpr auto apply(hana::experimental::types<T...> const&, U const&)
|
||||
-> hana::bool_<
|
||||
detail::any_of<is_same_as<typename U::type>::template apply, T...>::value
|
||||
>
|
||||
{ return {}; }
|
||||
|
||||
static constexpr hana::false_ apply(...) { return {}; }
|
||||
};
|
||||
|
||||
// Comparable
|
||||
template <>
|
||||
struct equal_impl<hana::experimental::types_tag, hana::experimental::types_tag> {
|
||||
template <typename Types>
|
||||
static constexpr hana::true_ apply(Types const&, Types const&)
|
||||
{ return {}; }
|
||||
|
||||
template <typename Ts, typename Us>
|
||||
static constexpr hana::false_ apply(Ts const&, Us const&)
|
||||
{ return {}; }
|
||||
};
|
||||
BOOST_HANA_NAMESPACE_END
|
||||
|
||||
#endif // !BOOST_HANA_EXPERIMENTAL_TYPES_HPP
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
@file
|
||||
Defines experimental views.
|
||||
|
||||
@copyright Louis Dionne 2013-2017
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef BOOST_HANA_EXPERIMENTAL_VIEW_HPP
|
||||
#define BOOST_HANA_EXPERIMENTAL_VIEW_HPP
|
||||
|
||||
#include <boost/hana/and.hpp>
|
||||
#include <boost/hana/at.hpp>
|
||||
#include <boost/hana/bool.hpp>
|
||||
#include <boost/hana/detail/decay.hpp>
|
||||
#include <boost/hana/fold_left.hpp>
|
||||
#include <boost/hana/functional/compose.hpp>
|
||||
#include <boost/hana/fwd/ap.hpp>
|
||||
#include <boost/hana/fwd/concat.hpp>
|
||||
#include <boost/hana/fwd/drop_front.hpp>
|
||||
#include <boost/hana/fwd/empty.hpp>
|
||||
#include <boost/hana/fwd/equal.hpp>
|
||||
#include <boost/hana/fwd/flatten.hpp>
|
||||
#include <boost/hana/fwd/is_empty.hpp>
|
||||
#include <boost/hana/fwd/less.hpp>
|
||||
#include <boost/hana/fwd/lift.hpp>
|
||||
#include <boost/hana/fwd/transform.hpp>
|
||||
#include <boost/hana/integral_constant.hpp>
|
||||
#include <boost/hana/length.hpp>
|
||||
#include <boost/hana/lexicographical_compare.hpp>
|
||||
#include <boost/hana/range.hpp>
|
||||
#include <boost/hana/tuple.hpp>
|
||||
#include <boost/hana/unpack.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
|
||||
// Pros of views
|
||||
// - No temporary container created between algorithms
|
||||
// - Lazy, so only the minimum is required
|
||||
//
|
||||
// Cons of views
|
||||
// - Reference semantics mean possibility for dangling references
|
||||
// - Lose the ability to move from temporary containers
|
||||
// - When fetching the members of a view multiple times, no caching is done.
|
||||
// So for example, `t = transform(xs, f); at_c<0>(t); at_c<0>(t)` will
|
||||
// compute `f(at_c<0>(xs))` twice.
|
||||
// - push_back creates a joint_view and a single_view. The single_view holds
|
||||
// the value as a member. When doing multiple push_backs, we end up with a
|
||||
// joint_view<xxx, joint_view<single_view<T>, joint_view<single_view<T>, ....>>>
|
||||
// which contains a reference to `xxx` and all the `T`s by value. Such a
|
||||
// "view" is not cheap to copy, which is inconsistent with the usual
|
||||
// expectations about views.
|
||||
|
||||
BOOST_HANA_NAMESPACE_BEGIN
|
||||
|
||||
namespace experimental {
|
||||
struct view_tag;
|
||||
|
||||
namespace detail {
|
||||
template <typename Sequence>
|
||||
struct is_view {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template <typename Sequence>
|
||||
using view_storage = typename std::conditional<
|
||||
detail::is_view<Sequence>::value, Sequence, Sequence&
|
||||
>::type;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// sliced_view
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename Sequence, std::size_t ...indices>
|
||||
struct sliced_view_t {
|
||||
detail::view_storage<Sequence> sequence_;
|
||||
using hana_tag = view_tag;
|
||||
};
|
||||
|
||||
template <typename Sequence, typename Indices>
|
||||
constexpr auto sliced(Sequence& sequence, Indices const& indices) {
|
||||
return hana::unpack(indices, [&](auto ...i) {
|
||||
return sliced_view_t<Sequence, decltype(i)::value...>{sequence};
|
||||
});
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename Sequence, std::size_t ...i>
|
||||
struct is_view<sliced_view_t<Sequence, i...>> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// transformed_view
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename Sequence, typename F>
|
||||
struct transformed_view_t {
|
||||
detail::view_storage<Sequence> sequence_;
|
||||
F f_;
|
||||
using hana_tag = view_tag;
|
||||
};
|
||||
|
||||
template <typename Sequence, typename F>
|
||||
constexpr transformed_view_t<Sequence, typename hana::detail::decay<F>::type>
|
||||
transformed(Sequence& sequence, F&& f) {
|
||||
return {sequence, static_cast<F&&>(f)};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename Sequence, typename F>
|
||||
struct is_view<transformed_view_t<Sequence, F>> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// filtered_view
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#if 0
|
||||
template <typename Sequence, typename Pred>
|
||||
using filtered_view_t = sliced_view_t<Sequence, detail::filtered_indices<...>>;
|
||||
|
||||
template <typename Sequence, typename Pred>
|
||||
constexpr filtered_view_t<Sequence, Pred> filtered(Sequence& sequence, Pred&& pred) {
|
||||
return {sequence};
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// joined_view
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename Sequence1, typename Sequence2>
|
||||
struct joined_view_t {
|
||||
detail::view_storage<Sequence1> sequence1_;
|
||||
detail::view_storage<Sequence2> sequence2_;
|
||||
using hana_tag = view_tag;
|
||||
};
|
||||
|
||||
struct make_joined_view_t {
|
||||
template <typename Sequence1, typename Sequence2>
|
||||
constexpr joined_view_t<Sequence1, Sequence2> operator()(Sequence1& s1, Sequence2& s2) const {
|
||||
return {s1, s2};
|
||||
}
|
||||
};
|
||||
constexpr make_joined_view_t joined{};
|
||||
|
||||
namespace detail {
|
||||
template <typename Sequence1, typename Sequence2>
|
||||
struct is_view<joined_view_t<Sequence1, Sequence2>> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// single_view
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
struct single_view_t {
|
||||
T value_;
|
||||
using hana_tag = view_tag;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr single_view_t<typename hana::detail::decay<T>::type> single_view(T&& t) {
|
||||
return {static_cast<T&&>(t)};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
struct is_view<single_view_t<T>> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// empty_view
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct empty_view_t {
|
||||
using hana_tag = view_tag;
|
||||
};
|
||||
|
||||
constexpr empty_view_t empty_view() {
|
||||
return {};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <>
|
||||
struct is_view<empty_view_t> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
}
|
||||
} // end namespace experimental
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Foldable
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct unpack_impl<experimental::view_tag> {
|
||||
// sliced_view
|
||||
template <typename Sequence, std::size_t ...i, typename F>
|
||||
static constexpr decltype(auto)
|
||||
apply(experimental::sliced_view_t<Sequence, i...> view, F&& f) {
|
||||
(void)view; // Remove spurious unused variable warning with GCC
|
||||
return static_cast<F&&>(f)(hana::at_c<i>(view.sequence_)...);
|
||||
}
|
||||
|
||||
// transformed_view
|
||||
template <typename Sequence, typename F, typename G>
|
||||
static constexpr decltype(auto)
|
||||
apply(experimental::transformed_view_t<Sequence, F> view, G&& g) {
|
||||
return hana::unpack(view.sequence_, hana::on(static_cast<G&&>(g), view.f_));
|
||||
}
|
||||
|
||||
// joined_view
|
||||
template <typename View, typename F, std::size_t ...i1, std::size_t ...i2>
|
||||
static constexpr decltype(auto)
|
||||
unpack_joined(View view, F&& f, std::index_sequence<i1...>,
|
||||
std::index_sequence<i2...>)
|
||||
{
|
||||
(void)view; // Remove spurious unused variable warning with GCC
|
||||
return static_cast<F&&>(f)(hana::at_c<i1>(view.sequence1_)...,
|
||||
hana::at_c<i2>(view.sequence2_)...);
|
||||
}
|
||||
|
||||
template <typename S1, typename S2, typename F>
|
||||
static constexpr decltype(auto)
|
||||
apply(experimental::joined_view_t<S1, S2> view, F&& f) {
|
||||
constexpr auto N1 = decltype(hana::length(view.sequence1_))::value;
|
||||
constexpr auto N2 = decltype(hana::length(view.sequence2_))::value;
|
||||
return unpack_joined(view, static_cast<F&&>(f),
|
||||
std::make_index_sequence<N1>{},
|
||||
std::make_index_sequence<N2>{});
|
||||
}
|
||||
|
||||
// single_view
|
||||
template <typename T, typename F>
|
||||
static constexpr decltype(auto) apply(experimental::single_view_t<T> view, F&& f) {
|
||||
return static_cast<F&&>(f)(view.value_);
|
||||
}
|
||||
|
||||
// empty_view
|
||||
template <typename F>
|
||||
static constexpr decltype(auto) apply(experimental::empty_view_t, F&& f) {
|
||||
return static_cast<F&&>(f)();
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Iterable
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct at_impl<experimental::view_tag> {
|
||||
// sliced_view
|
||||
template <typename Sequence, std::size_t ...i, typename N>
|
||||
static constexpr decltype(auto)
|
||||
apply(experimental::sliced_view_t<Sequence, i...> view, N const&) {
|
||||
constexpr std::size_t indices[] = {i...};
|
||||
constexpr std::size_t n = indices[N::value];
|
||||
return hana::at_c<n>(view.sequence_);
|
||||
}
|
||||
|
||||
// transformed_view
|
||||
template <typename Sequence, typename F, typename N>
|
||||
static constexpr decltype(auto)
|
||||
apply(experimental::transformed_view_t<Sequence, F> view, N const& n) {
|
||||
return view.f_(hana::at(view.sequence_, n));
|
||||
}
|
||||
|
||||
// joined_view
|
||||
template <std::size_t Left, typename View, typename N>
|
||||
static constexpr decltype(auto) at_joined_view(View view, N const&, hana::true_) {
|
||||
return hana::at_c<N::value>(view.sequence1_);
|
||||
}
|
||||
|
||||
template <std::size_t Left, typename View, typename N>
|
||||
static constexpr decltype(auto) at_joined_view(View view, N const&, hana::false_) {
|
||||
return hana::at_c<N::value - Left>(view.sequence2_);
|
||||
}
|
||||
|
||||
template <typename S1, typename S2, typename N>
|
||||
static constexpr decltype(auto)
|
||||
apply(experimental::joined_view_t<S1, S2> view, N const& n) {
|
||||
constexpr auto Left = decltype(hana::length(view.sequence1_))::value;
|
||||
return at_joined_view<Left>(view, n, hana::bool_c<(N::value < Left)>);
|
||||
}
|
||||
|
||||
// single_view
|
||||
template <typename T, typename N>
|
||||
static constexpr decltype(auto) apply(experimental::single_view_t<T> view, N const&) {
|
||||
static_assert(N::value == 0,
|
||||
"trying to fetch an out-of-bounds element in a hana::single_view");
|
||||
return view.value_;
|
||||
}
|
||||
|
||||
// empty_view
|
||||
template <typename N>
|
||||
static constexpr decltype(auto) apply(experimental::empty_view_t, N const&) = delete;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct length_impl<experimental::view_tag> {
|
||||
// sliced_view
|
||||
template <typename Sequence, std::size_t ...i>
|
||||
static constexpr auto
|
||||
apply(experimental::sliced_view_t<Sequence, i...>) {
|
||||
return hana::size_c<sizeof...(i)>;
|
||||
}
|
||||
|
||||
// transformed_view
|
||||
template <typename Sequence, typename F>
|
||||
static constexpr auto apply(experimental::transformed_view_t<Sequence, F> view) {
|
||||
return hana::length(view.sequence_);
|
||||
}
|
||||
|
||||
// joined_view
|
||||
template <typename S1, typename S2>
|
||||
static constexpr auto apply(experimental::joined_view_t<S1, S2> view) {
|
||||
return hana::size_c<
|
||||
decltype(hana::length(view.sequence1_))::value +
|
||||
decltype(hana::length(view.sequence2_))::value
|
||||
>;
|
||||
}
|
||||
|
||||
// single_view
|
||||
template <typename T>
|
||||
static constexpr auto apply(experimental::single_view_t<T>) {
|
||||
return hana::size_c<1>;
|
||||
}
|
||||
|
||||
// empty_view
|
||||
static constexpr auto apply(experimental::empty_view_t) {
|
||||
return hana::size_c<0>;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_empty_impl<experimental::view_tag> {
|
||||
// sliced_view
|
||||
template <typename Sequence, std::size_t ...i>
|
||||
static constexpr auto
|
||||
apply(experimental::sliced_view_t<Sequence, i...>) {
|
||||
return hana::bool_c<sizeof...(i) == 0>;
|
||||
}
|
||||
|
||||
// transformed_view
|
||||
template <typename Sequence, typename F>
|
||||
static constexpr auto apply(experimental::transformed_view_t<Sequence, F> view) {
|
||||
return hana::is_empty(view.sequence_);
|
||||
}
|
||||
|
||||
// joined_view
|
||||
template <typename S1, typename S2>
|
||||
static constexpr auto apply(experimental::joined_view_t<S1, S2> view) {
|
||||
return hana::and_(hana::is_empty(view.sequence1_),
|
||||
hana::is_empty(view.sequence2_));
|
||||
}
|
||||
|
||||
// single_view
|
||||
template <typename T>
|
||||
static constexpr auto apply(experimental::single_view_t<T>) {
|
||||
return hana::false_c;
|
||||
}
|
||||
|
||||
// empty_view
|
||||
static constexpr auto apply(experimental::empty_view_t) {
|
||||
return hana::true_c;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct drop_front_impl<experimental::view_tag> {
|
||||
template <typename View, typename N>
|
||||
static constexpr auto apply(View view, N const&) {
|
||||
constexpr auto n = N::value;
|
||||
constexpr auto Length = decltype(hana::length(view))::value;
|
||||
return experimental::sliced(view, hana::range_c<std::size_t, n, Length>);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Functor
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct transform_impl<experimental::view_tag> {
|
||||
template <typename Sequence, typename F, typename G>
|
||||
static constexpr auto
|
||||
apply(experimental::transformed_view_t<Sequence, F> view, G&& g) {
|
||||
return experimental::transformed(view.sequence_,
|
||||
hana::compose(static_cast<G&&>(g), view.f_));
|
||||
}
|
||||
|
||||
template <typename View, typename F>
|
||||
static constexpr auto apply(View view, F&& f) {
|
||||
return experimental::transformed(view, static_cast<F&&>(f));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Applicative
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct lift_impl<experimental::view_tag> {
|
||||
template <typename T>
|
||||
static constexpr auto apply(T&& t) {
|
||||
return experimental::single_view(static_cast<T&&>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ap_impl<experimental::view_tag> {
|
||||
template <typename F, typename X>
|
||||
static constexpr auto apply(F&& f, X&& x) {
|
||||
// TODO: Implement cleverly; we most likely need a cartesian_product
|
||||
// view or something like that.
|
||||
return hana::ap(hana::to_tuple(f), hana::to_tuple(x));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Monad
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct flatten_impl<experimental::view_tag> {
|
||||
template <typename View>
|
||||
static constexpr auto apply(View view) {
|
||||
// TODO: Implement a flattened_view instead
|
||||
return hana::fold_left(view, experimental::empty_view(),
|
||||
experimental::joined);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// MonadPlus
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct concat_impl<experimental::view_tag> {
|
||||
template <typename View1, typename View2>
|
||||
static constexpr auto apply(View1 view1, View2 view2) {
|
||||
return experimental::joined(view1, view2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct empty_impl<experimental::view_tag> {
|
||||
static constexpr auto apply() {
|
||||
return experimental::empty_view();
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Comparable
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct equal_impl<experimental::view_tag, experimental::view_tag> {
|
||||
template <typename View1, typename View2>
|
||||
static constexpr auto apply(View1 v1, View2 v2) {
|
||||
// TODO: Use a lexicographical comparison algorithm.
|
||||
return hana::equal(hana::to_tuple(v1), hana::to_tuple(v2));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
struct equal_impl<experimental::view_tag, S, hana::when<hana::Sequence<S>::value>> {
|
||||
template <typename View1, typename Seq>
|
||||
static constexpr auto apply(View1 v1, Seq const& s) {
|
||||
// TODO: Use a lexicographical comparison algorithm.
|
||||
return hana::equal(hana::to_tuple(v1), hana::to_tuple(s));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
struct equal_impl<S, experimental::view_tag, hana::when<hana::Sequence<S>::value>> {
|
||||
template <typename Seq, typename View2>
|
||||
static constexpr auto apply(Seq const& s, View2 v2) {
|
||||
// TODO: Use a lexicographical comparison algorithm.
|
||||
return hana::equal(hana::to_tuple(s), hana::to_tuple(v2));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Orderable
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <>
|
||||
struct less_impl<experimental::view_tag, experimental::view_tag> {
|
||||
template <typename View1, typename View2>
|
||||
static constexpr auto apply(View1 v1, View2 v2) {
|
||||
return hana::lexicographical_compare(v1, v2);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
struct less_impl<experimental::view_tag, S, hana::when<hana::Sequence<S>::value>> {
|
||||
template <typename View1, typename Seq>
|
||||
static constexpr auto apply(View1 v1, Seq const& s) {
|
||||
return hana::lexicographical_compare(v1, s);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename S>
|
||||
struct less_impl<S, experimental::view_tag, hana::when<hana::Sequence<S>::value>> {
|
||||
template <typename Seq, typename View2>
|
||||
static constexpr auto apply(Seq const& s, View2 v2) {
|
||||
return hana::lexicographical_compare(s, v2);
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_HANA_NAMESPACE_END
|
||||
|
||||
#endif // !BOOST_HANA_EXPERIMENTAL_VIEW_HPP
|
||||
Reference in New Issue
Block a user