summaryrefslogtreecommitdiff
path: root/boost/hof/returns.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hof/returns.hpp')
-rw-r--r--boost/hof/returns.hpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/boost/hof/returns.hpp b/boost/hof/returns.hpp
new file mode 100644
index 0000000000..5360a38314
--- /dev/null
+++ b/boost/hof/returns.hpp
@@ -0,0 +1,249 @@
+/*=============================================================================
+ Copyright (c) 2014 Paul Fultz II
+ returns.h
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#ifndef BOOST_HOF_GUARD_RETURNS_H
+#define BOOST_HOF_GUARD_RETURNS_H
+
+/// BOOST_HOF_RETURNS
+/// ===========
+///
+/// Description
+/// -----------
+///
+/// The `BOOST_HOF_RETURNS` macro defines the function as the expression
+/// equivalence. It does this by deducing `noexcept` and the return type by
+/// using a trailing `decltype`. Instead of repeating the expression for the
+/// return type, `noexcept` clause and the function body, this macro will
+/// reduce the code duplication from that.
+///
+/// Note: The expression used to deduce the return the type will also
+/// constrain the template function and deduce `noexcept` as well, which is
+/// different behaviour than using C++14's return type deduction.
+///
+/// Synopsis
+/// --------
+///
+/// #define BOOST_HOF_RETURNS(...)
+///
+///
+/// Example
+/// -------
+///
+/// #include <boost/hof.hpp>
+/// #include <cassert>
+///
+/// template<class T, class U>
+/// auto sum(T x, U y) BOOST_HOF_RETURNS(x+y);
+///
+/// int main() {
+/// assert(3 == sum(1, 2));
+/// }
+///
+///
+/// Incomplete this
+/// ---------------
+///
+/// Description
+/// -----------
+///
+/// On some non-conformant compilers, such as gcc, the `this` variable cannot
+/// be used inside the `BOOST_HOF_RETURNS` macro because it is considered an
+/// incomplete type. So the following macros are provided to help workaround
+/// the issue.
+///
+///
+/// Synopsis
+/// --------
+///
+/// // Declares the type of the `this` variable
+/// #define BOOST_HOF_RETURNS_CLASS(...)
+/// // Used to refer to the `this` variable in the BOOST_HOF_RETURNS macro
+/// #define BOOST_HOF_THIS
+/// // Used to refer to the const `this` variable in the BOOST_HOF_RETURNS macro
+/// #define BOOST_HOF_CONST_THIS
+///
+///
+/// Example
+/// -------
+///
+/// #include <boost/hof.hpp>
+/// #include <cassert>
+///
+/// struct add_1
+/// {
+/// int a;
+/// add_1() : a(1) {}
+///
+/// BOOST_HOF_RETURNS_CLASS(add_1);
+///
+/// template<class T>
+/// auto operator()(T x) const
+/// BOOST_HOF_RETURNS(x+BOOST_HOF_CONST_THIS->a);
+/// };
+///
+/// int main() {
+/// assert(3 == add_1()(2));
+/// }
+///
+///
+/// Mangling overloads
+/// ------------------
+///
+/// Description
+/// -----------
+///
+/// On older compilers some operations done in the expressions cannot be
+/// properly mangled. These macros help provide workarounds for these
+/// operations on older compilers.
+///
+///
+/// Synopsis
+/// --------
+///
+/// // Explicitly defines the type for name mangling
+/// #define BOOST_HOF_MANGLE_CAST(...)
+/// // C cast for name mangling
+/// #define BOOST_HOF_RETURNS_C_CAST(...)
+/// // Reinterpret cast for name mangling
+/// #define BOOST_HOF_RETURNS_REINTERPRET_CAST(...)
+/// // Static cast for name mangling
+/// #define BOOST_HOF_RETURNS_STATIC_CAST(...)
+/// // Construction for name mangling
+/// #define BOOST_HOF_RETURNS_CONSTRUCT(...)
+///
+
+
+#include <boost/hof/config.hpp>
+#include <utility>
+#include <boost/hof/detail/forward.hpp>
+#include <boost/hof/detail/noexcept.hpp>
+
+#define BOOST_HOF_EAT(...)
+#define BOOST_HOF_REM(...) __VA_ARGS__
+
+#if BOOST_HOF_HAS_COMPLETE_DECLTYPE && BOOST_HOF_HAS_MANGLE_OVERLOAD
+#ifdef _MSC_VER
+// Since decltype can't be used in noexcept on MSVC, we can't check for noexcept
+// move constructors.
+#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(__VA_ARGS__))
+#else
+#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(static_cast<decltype(__VA_ARGS__)>(__VA_ARGS__)))
+#endif
+#define BOOST_HOF_RETURNS(...) \
+BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(__VA_ARGS__) \
+-> decltype(__VA_ARGS__) { return __VA_ARGS__; }
+#define BOOST_HOF_THIS this
+#define BOOST_HOF_CONST_THIS this
+#define BOOST_HOF_RETURNS_CLASS(...) \
+void fit_returns_class_check() \
+{ \
+ static_assert(std::is_same<__VA_ARGS__*, decltype(this)>::value, \
+ "Returns class " #__VA_ARGS__ " type doesn't match"); \
+}
+
+#define BOOST_HOF_MANGLE_CAST(...) BOOST_HOF_REM
+
+#define BOOST_HOF_RETURNS_C_CAST(...) (__VA_ARGS__) BOOST_HOF_REM
+#define BOOST_HOF_RETURNS_REINTERPRET_CAST(...) reinterpret_cast<__VA_ARGS__>
+#define BOOST_HOF_RETURNS_STATIC_CAST(...) static_cast<__VA_ARGS__>
+#define BOOST_HOF_RETURNS_CONSTRUCT(...) __VA_ARGS__
+#else
+#include <boost/hof/detail/pp.hpp>
+
+#define BOOST_HOF_RETURNS_RETURN(...) return BOOST_HOF_RETURNS_RETURN_X(BOOST_HOF_PP_WALL(__VA_ARGS__))
+#define BOOST_HOF_RETURNS_RETURN_X(...) __VA_ARGS__
+
+#ifdef _MSC_VER
+// Since decltype can't be used in noexcept on MSVC, we can't check for noexcept
+// move constructors.
+#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__)))
+#else
+#define BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(...) BOOST_HOF_NOEXCEPT(noexcept(static_cast<decltype(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__))>(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__))))
+#endif
+
+#define BOOST_HOF_RETURNS_DECLTYPE(...) \
+-> decltype(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(__VA_ARGS__))
+
+#define BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(...) BOOST_HOF_RETURNS_DECLTYPE_CONTEXT_X(BOOST_HOF_PP_WALL(__VA_ARGS__))
+#define BOOST_HOF_RETURNS_DECLTYPE_CONTEXT_X(...) __VA_ARGS__
+
+#define BOOST_HOF_RETURNS_THAT(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
+ (boost::hof::detail::check_this<__VA_ARGS__, decltype(this)>(), this), \
+ std::declval<__VA_ARGS__>() \
+)
+
+#define BOOST_HOF_THIS BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_THAT)(fit_this_type)
+#define BOOST_HOF_CONST_THIS BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_THAT)(fit_const_this_type)
+
+#define BOOST_HOF_RETURNS_CLASS(...) typedef __VA_ARGS__* fit_this_type; typedef const __VA_ARGS__* fit_const_this_type
+
+#define BOOST_HOF_RETURNS(...) \
+BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(__VA_ARGS__) \
+BOOST_HOF_RETURNS_DECLTYPE(__VA_ARGS__) \
+{ BOOST_HOF_RETURNS_RETURN(__VA_ARGS__); }
+
+
+namespace boost { namespace hof { namespace detail {
+template<class Assumed, class T>
+struct check_this
+{
+ static_assert(std::is_same<T, Assumed>::value, "Incorret BOOST_HOF_THIS or BOOST_HOF_CONST_THIS used.");
+};
+
+}}} // namespace boost::hof
+
+#endif
+
+
+#if BOOST_HOF_HAS_MANGLE_OVERLOAD
+
+#define BOOST_HOF_MANGLE_CAST(...) BOOST_HOF_REM
+
+#define BOOST_HOF_RETURNS_C_CAST(...) (__VA_ARGS__) BOOST_HOF_REM
+#define BOOST_HOF_RETURNS_REINTERPRET_CAST(...) reinterpret_cast<__VA_ARGS__>
+#define BOOST_HOF_RETURNS_STATIC_CAST(...) static_cast<__VA_ARGS__>
+#define BOOST_HOF_RETURNS_CONSTRUCT(...) __VA_ARGS__
+
+#else
+
+#define BOOST_HOF_RETURNS_DERAIL_MANGLE_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
+ BOOST_HOF_REM, \
+ std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
+)
+#define BOOST_HOF_MANGLE_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_MANGLE_CAST)
+
+
+#define BOOST_HOF_RETURNS_DERAIL_C_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
+ (__VA_ARGS__) BOOST_HOF_REM, \
+ std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
+)
+#define BOOST_HOF_RETURNS_C_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_C_CAST)
+
+
+#define BOOST_HOF_RETURNS_DERAIL_REINTERPRET_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
+ reinterpret_cast<__VA_ARGS__>, \
+ std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
+)
+#define BOOST_HOF_RETURNS_REINTERPRET_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_REINTERPRET_CAST)
+
+#define BOOST_HOF_RETURNS_DERAIL_STATIC_CAST(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
+ static_cast<__VA_ARGS__>, \
+ std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
+)
+#define BOOST_HOF_RETURNS_STATIC_CAST BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_STATIC_CAST)
+
+#define BOOST_HOF_RETURNS_DERAIL_CONSTRUCT(...) BOOST_HOF_PP_IIF(BOOST_HOF_PP_IS_PAREN(BOOST_HOF_RETURNS_DECLTYPE_CONTEXT(())))(\
+ __VA_ARGS__, \
+ std::declval<__VA_ARGS__>() BOOST_HOF_EAT \
+)
+#define BOOST_HOF_RETURNS_CONSTRUCT BOOST_HOF_PP_RAIL(BOOST_HOF_RETURNS_DERAIL_CONSTRUCT)
+
+#endif
+
+#define BOOST_HOF_AUTO_FORWARD(...) BOOST_HOF_RETURNS_STATIC_CAST(decltype(__VA_ARGS__))(__VA_ARGS__)
+
+#endif