stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
/*!
|
||||
@file
|
||||
Defines `boost::hana::_`.
|
||||
|
||||
@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_FUNCTIONAL_PLACEHOLDER_HPP
|
||||
#define BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
|
||||
|
||||
#include <boost/hana/basic_tuple.hpp>
|
||||
#include <boost/hana/config.hpp>
|
||||
#include <boost/hana/detail/create.hpp>
|
||||
#include <boost/hana/detail/decay.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
|
||||
BOOST_HANA_NAMESPACE_BEGIN
|
||||
//! @ingroup group-functional
|
||||
//! Create simple functions representing C++ operators inline.
|
||||
//!
|
||||
//! Specifically, `_` is an object used as a placeholder to build
|
||||
//! function objects representing calls to C++ operators. It works
|
||||
//! by overloading the operators between `_` and any object so that
|
||||
//! they return a function object which actually calls the corresponding
|
||||
//! operator on its argument(s). Hence, for any supported operator `@`:
|
||||
//! @code
|
||||
//! (_ @ _)(x, y) == x @ y
|
||||
//! @endcode
|
||||
//!
|
||||
//! Operators may also be partially applied to one argument inline:
|
||||
//! @code
|
||||
//! (x @ _)(y) == x @ y
|
||||
//! (_ @ y)(x) == x @ y
|
||||
//! @endcode
|
||||
//!
|
||||
//! When invoked with more arguments than required, functions created with
|
||||
//! `_` will discard the superfluous instead of triggering an error:
|
||||
//! @code
|
||||
//! (_ @ _)(x, y, z...) == x @ y
|
||||
//! @endcode
|
||||
//!
|
||||
//! This makes functions created with `_` easier to use in higher-order
|
||||
//! algorithms, which sometime provide more information than necessary
|
||||
//! to their callbacks.
|
||||
//!
|
||||
//! ### Supported operators
|
||||
//! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
|
||||
//! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
|
||||
//! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
|
||||
//! - %Logical: `||`, `&&`, `!`
|
||||
//! - Member access: `*` (dereference), `[]` (array subscript)
|
||||
//! - Other: `()` (function call)
|
||||
//!
|
||||
//! More complex functionality like the ability to compose placeholders
|
||||
//! into larger function objects inline are not supported. This is on
|
||||
//! purpose; you should either use C++14 generic lambdas or a library
|
||||
//! like [Boost.Phoenix][] if you need bigger guns. The goal here is
|
||||
//! to save you a couple of characters in simple situations.
|
||||
//!
|
||||
//! ### Example
|
||||
//! @include example/functional/placeholder.cpp
|
||||
//!
|
||||
//! [Boost.Phoenix]: http://www.boost.org/doc/libs/release/libs/phoenix/doc/html/index.html
|
||||
#ifdef BOOST_HANA_DOXYGEN_INVOKED
|
||||
constexpr unspecified _{};
|
||||
#else
|
||||
namespace placeholder_detail {
|
||||
template <typename I>
|
||||
struct subscript {
|
||||
I i;
|
||||
|
||||
template <typename Xs, typename ...Z>
|
||||
constexpr auto operator()(Xs&& xs, Z const& ...) const&
|
||||
-> decltype(static_cast<Xs&&>(xs)[i])
|
||||
{ return static_cast<Xs&&>(xs)[i]; }
|
||||
|
||||
template <typename Xs, typename ...Z>
|
||||
constexpr auto operator()(Xs&& xs, Z const& ...) &
|
||||
-> decltype(static_cast<Xs&&>(xs)[i])
|
||||
{ return static_cast<Xs&&>(xs)[i]; }
|
||||
|
||||
template <typename Xs, typename ...Z>
|
||||
constexpr auto operator()(Xs&& xs, Z const& ...) &&
|
||||
-> decltype(static_cast<Xs&&>(xs)[std::declval<I>()])
|
||||
{ return static_cast<Xs&&>(xs)[std::move(i)]; }
|
||||
};
|
||||
|
||||
template <typename F, typename Xs, std::size_t ...i>
|
||||
constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence<i...>) {
|
||||
return static_cast<F&&>(f)(hana::at_c<i>(static_cast<Xs&&>(xs).storage_)...);
|
||||
}
|
||||
|
||||
template <typename ...X>
|
||||
struct invoke;
|
||||
|
||||
struct placeholder {
|
||||
struct secret { };
|
||||
|
||||
template <typename X>
|
||||
constexpr decltype(auto) operator[](X&& x) const
|
||||
{ return detail::create<subscript>{}(static_cast<X&&>(x)); }
|
||||
|
||||
template <typename ...X>
|
||||
constexpr invoke<typename detail::decay<X>::type...>
|
||||
operator()(X&& ...x) const {
|
||||
return {secret{}, static_cast<X&&>(x)...};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ...X>
|
||||
struct invoke {
|
||||
template <typename ...Y>
|
||||
constexpr invoke(placeholder::secret, Y&& ...y)
|
||||
: storage_{static_cast<Y&&>(y)...}
|
||||
{ }
|
||||
|
||||
basic_tuple<X...> storage_;
|
||||
|
||||
template <typename F, typename ...Z>
|
||||
constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(
|
||||
static_cast<F&&>(f)(std::declval<X const&>()...)
|
||||
) {
|
||||
return invoke_impl(static_cast<F&&>(f), *this,
|
||||
std::make_index_sequence<sizeof...(X)>{});
|
||||
}
|
||||
|
||||
template <typename F, typename ...Z>
|
||||
constexpr auto operator()(F&& f, Z const& ...) & -> decltype(
|
||||
static_cast<F&&>(f)(std::declval<X&>()...)
|
||||
) {
|
||||
return invoke_impl(static_cast<F&&>(f), *this,
|
||||
std::make_index_sequence<sizeof...(X)>{});
|
||||
}
|
||||
|
||||
template <typename F, typename ...Z>
|
||||
constexpr auto operator()(F&& f, Z const& ...) && -> decltype(
|
||||
static_cast<F&&>(f)(std::declval<X&&>()...)
|
||||
) {
|
||||
return invoke_impl(static_cast<F&&>(f), static_cast<invoke&&>(*this),
|
||||
std::make_index_sequence<sizeof...(X)>{});
|
||||
}
|
||||
};
|
||||
|
||||
#define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name) \
|
||||
template <typename X> \
|
||||
struct op_name ## _left { \
|
||||
X x; \
|
||||
\
|
||||
template <typename Y, typename ...Z> \
|
||||
constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype( \
|
||||
std::declval<X const&>() op static_cast<Y&&>(y)) \
|
||||
{ return x op static_cast<Y&&>(y); } \
|
||||
\
|
||||
template <typename Y, typename ...Z> \
|
||||
constexpr auto operator()(Y&& y, Z const& ...) & -> decltype( \
|
||||
std::declval<X&>() op static_cast<Y&&>(y)) \
|
||||
{ return x op static_cast<Y&&>(y); } \
|
||||
\
|
||||
template <typename Y, typename ...Z> \
|
||||
constexpr auto operator()(Y&& y, Z const& ...) && -> decltype( \
|
||||
std::declval<X>() op static_cast<Y&&>(y)) \
|
||||
{ return std::move(x) op static_cast<Y&&>(y); } \
|
||||
}; \
|
||||
\
|
||||
template <typename Y> \
|
||||
struct op_name ## _right { \
|
||||
Y y; \
|
||||
\
|
||||
template <typename X, typename ...Z> \
|
||||
constexpr auto operator()(X&& x, Z const& ...) const& -> decltype( \
|
||||
static_cast<X&&>(x) op std::declval<Y const&>()) \
|
||||
{ return static_cast<X&&>(x) op y; } \
|
||||
\
|
||||
template <typename X, typename ...Z> \
|
||||
constexpr auto operator()(X&& x, Z const& ...) & -> decltype( \
|
||||
static_cast<X&&>(x) op std::declval<Y&>()) \
|
||||
{ return static_cast<X&&>(x) op y; } \
|
||||
\
|
||||
template <typename X, typename ...Z> \
|
||||
constexpr auto operator()(X&& x, Z const& ...) && -> decltype( \
|
||||
static_cast<X&&>(x) op std::declval<Y>()) \
|
||||
{ return static_cast<X&&>(x) op std::move(y); } \
|
||||
}; \
|
||||
\
|
||||
struct op_name { \
|
||||
template <typename X, typename Y, typename ...Z> \
|
||||
constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\
|
||||
static_cast<X&&>(x) op static_cast<Y&&>(y)) \
|
||||
{ return static_cast<X&&>(x) op static_cast<Y&&>(y); } \
|
||||
}; \
|
||||
\
|
||||
template <typename X> \
|
||||
constexpr decltype(auto) operator op (X&& x, placeholder) \
|
||||
{ return detail::create<op_name ## _left>{}(static_cast<X&&>(x)); } \
|
||||
\
|
||||
template <typename Y> \
|
||||
constexpr decltype(auto) operator op (placeholder, Y&& y) \
|
||||
{ return detail::create<op_name ## _right>{}(static_cast<Y&&>(y)); } \
|
||||
\
|
||||
inline constexpr decltype(auto) operator op (placeholder, placeholder) \
|
||||
{ return op_name{}; } \
|
||||
/**/
|
||||
|
||||
#define BOOST_HANA_PLACEHOLDER_UNARY_OP(op, op_name) \
|
||||
struct op_name { \
|
||||
template <typename X, typename ...Z> \
|
||||
constexpr auto operator()(X&& x, Z const& ...) const \
|
||||
-> decltype(op static_cast<X&&>(x)) \
|
||||
{ return op static_cast<X&&>(x); } \
|
||||
}; \
|
||||
\
|
||||
inline constexpr decltype(auto) operator op (placeholder) \
|
||||
{ return op_name{}; } \
|
||||
/**/
|
||||
// Arithmetic
|
||||
BOOST_HANA_PLACEHOLDER_UNARY_OP(+, unary_plus)
|
||||
BOOST_HANA_PLACEHOLDER_UNARY_OP(-, unary_minus)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(+, plus)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(-, minus)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(*, times)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(/, divide)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(%, modulo)
|
||||
|
||||
// Bitwise
|
||||
BOOST_HANA_PLACEHOLDER_UNARY_OP(~, bitwise_not)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(&, bitwise_and)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(|, bitwise_or)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(^, bitwise_xor)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(<<, left_shift)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(>>, right_shift)
|
||||
|
||||
// Comparison
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(==, equal)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(!=, not_equal)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(<, less)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(<=, less_equal)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(>, greater)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(>=, greater_equal)
|
||||
|
||||
// Logical
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(||, logical_or)
|
||||
BOOST_HANA_PLACEHOLDER_BINARY_OP(&&, logical_and)
|
||||
BOOST_HANA_PLACEHOLDER_UNARY_OP(!, logical_not)
|
||||
|
||||
// Member access (array subscript is a member function)
|
||||
BOOST_HANA_PLACEHOLDER_UNARY_OP(*, dereference)
|
||||
|
||||
// Other (function call is a member function)
|
||||
|
||||
#undef BOOST_HANA_PREFIX_PLACEHOLDER_OP
|
||||
#undef BOOST_HANA_BINARY_PLACEHOLDER_OP
|
||||
} // end namespace placeholder_detail
|
||||
|
||||
constexpr placeholder_detail::placeholder _{};
|
||||
#endif
|
||||
BOOST_HANA_NAMESPACE_END
|
||||
|
||||
#endif // !BOOST_HANA_FUNCTIONAL_PLACEHOLDER_HPP
|
||||
Reference in New Issue
Block a user