/usr/include/boost/hana/functional
Edit: /usr/include/boost/hana/functional/placeholder.hpp (12985B)
/*!
@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
#include
#include
#include
#include
#include
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
struct subscript {
I i;
template
constexpr auto operator()(Xs&& xs, Z const& ...) const&
-> decltype(static_cast(xs)[i])
{ return static_cast(xs)[i]; }
template
constexpr auto operator()(Xs&& xs, Z const& ...) &
-> decltype(static_cast(xs)[i])
{ return static_cast(xs)[i]; }
template
constexpr auto operator()(Xs&& xs, Z const& ...) &&
-> decltype(static_cast(xs)[std::declval()])
{ return static_cast(xs)[std::move(i)]; }
};
template
constexpr decltype(auto) invoke_impl(F&& f, Xs&& xs, std::index_sequence) {
return static_cast(f)(hana::at_c(static_cast(xs).storage_)...);
}
template
struct invoke;
struct placeholder {
struct secret { };
template
constexpr decltype(auto) operator[](X&& x) const
{ return detail::create{}(static_cast(x)); }
template
constexpr invoke::type...>
operator()(X&& ...x) const {
return {secret{}, static_cast(x)...};
}
};
template
struct invoke {
template
constexpr invoke(placeholder::secret, Y&& ...y)
: storage_{static_cast(y)...}
{ }
basic_tuple storage_;
template
constexpr auto operator()(F&& f, Z const& ...) const& -> decltype(
static_cast(f)(std::declval()...)
) {
return invoke_impl(static_cast(f), *this,
std::make_index_sequence{});
}
template
constexpr auto operator()(F&& f, Z const& ...) & -> decltype(
static_cast(f)(std::declval()...)
) {
return invoke_impl(static_cast(f), *this,
std::make_index_sequence{});
}
template
constexpr auto operator()(F&& f, Z const& ...) && -> decltype(
static_cast(f)(std::declval()...)
) {
return invoke_impl(static_cast(f), static_cast(*this),
std::make_index_sequence{});
}
};
#define BOOST_HANA_PLACEHOLDER_BINARY_OP(op, op_name) \
template \
struct op_name ## _left { \
X x; \
\
template \
constexpr auto operator()(Y&& y, Z const& ...) const& -> decltype( \
std::declval() op static_cast(y)) \
{ return x op static_cast(y); } \
\
template \
constexpr auto operator()(Y&& y, Z const& ...) & -> decltype( \
std::declval() op static_cast(y)) \
{ return x op static_cast(y); } \
\
template \
constexpr auto operator()(Y&& y, Z const& ...) && -> decltype( \
std::declval() op static_cast(y)) \
{ return std::move(x) op static_cast(y); } \
}; \
\
template \
struct op_name ## _right { \
Y y; \
\
template \
constexpr auto operator()(X&& x, Z const& ...) const& -> decltype( \
static_cast(x) op std::declval()) \
{ return static_cast(x) op y; } \
\
template \
constexpr auto operator()(X&& x, Z const& ...) & -> decltype( \
static_cast(x) op std::declval()) \
{ return static_cast(x) op y; } \
\
template \
constexpr auto operator()(X&& x, Z const& ...) && -> decltype( \
static_cast(x) op std::declval()) \
{ return static_cast(x) op std::move(y); } \
}; \
\
struct op_name { \
template \
constexpr auto operator()(X&& x, Y&& y, Z const& ...) const -> decltype(\
static_cast(x) op static_cast(y)) \
{ return static_cast(x) op static_cast(y); } \
}; \
\
template \
constexpr decltype(auto) operator op (X&& x, placeholder) \
{ return detail::create{}(static_cast(x)); } \
\
template \
constexpr decltype(auto) operator op (placeholder, Y&& y) \
{ return detail::create{}(static_cast(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 \
constexpr auto operator()(X&& x, Z const& ...) const \
-> decltype(op static_cast(x)) \
{ return op static_cast(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