summaryrefslogtreecommitdiff
path: root/boost/hana/fwd/unpack.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hana/fwd/unpack.hpp')
-rw-r--r--boost/hana/fwd/unpack.hpp103
1 files changed, 103 insertions, 0 deletions
diff --git a/boost/hana/fwd/unpack.hpp b/boost/hana/fwd/unpack.hpp
new file mode 100644
index 0000000000..43a4941f3e
--- /dev/null
+++ b/boost/hana/fwd/unpack.hpp
@@ -0,0 +1,103 @@
+/*!
+@file
+Forward declares `boost::hana::unpack`.
+
+@copyright Louis Dionne 2013-2016
+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_FWD_UNPACK_HPP
+#define BOOST_HANA_FWD_UNPACK_HPP
+
+#include <boost/hana/config.hpp>
+#include <boost/hana/core/when.hpp>
+
+
+BOOST_HANA_NAMESPACE_BEGIN
+ //! Invoke a function with the elements of a Foldable as arguments.
+ //! @ingroup group-Foldable
+ //!
+ //! Given a function and a foldable structure whose length can be known at
+ //! compile-time, `unpack` invokes the function with the contents of that
+ //! structure. In other words, `unpack(xs, f)` is equivalent to `f(x...)`,
+ //! where `x...` are the elements of the structure. The length of the
+ //! structure must be known at compile-time, because the version of `f`'s
+ //! `operator()` that will be compiled depends on the number of arguments
+ //! it is called with, which has to be known at compile-time.
+ //!
+ //! To create a function that accepts a foldable instead of variadic
+ //! arguments, see `fuse` instead.
+ //!
+ //!
+ //! @param xs
+ //! The structure to expand into the function.
+ //!
+ //! @param f
+ //! A function to be invoked as `f(x...)`, where `x...` are the elements
+ //! of the structure as-if they had been linearized with `to<tuple_tag>`.
+ //!
+ //!
+ //! Example
+ //! -------
+ //! @include example/unpack.cpp
+ //!
+ //!
+ //! Benchmarks
+ //! ----------
+ //! <div class="benchmark-chart"
+ //! style="min-width: 310px; height: 400px; margin: 0 auto"
+ //! data-dataset="benchmark.unpack.compile.json">
+ //! </div>
+ //!
+ //!
+ //! Rationale: `unpack`'s name and parameter order
+ //! ----------------------------------------------
+ //! It has been suggested a couple of times that `unpack` be called
+ //! `apply` instead, and that the parameter order be reversed to match
+ //! that of the [proposed std::apply function][1]. However, the name
+ //! `apply` is already used to denote normal function application, an use
+ //! which is consistent with the Boost MPL library and with the rest of
+ //! the world, especially the functional programming community.
+ //! Furthermore, the author of this library considers the proposed
+ //! `std::apply` to have both an unfortunate name and an unfortunate
+ //! parameter order. Indeed, taking the function as the first argument
+ //! means that using `std::apply` with a lambda function looks like
+ //! @code
+ //! std::apply([](auto ...args) {
+ //! use(args...);
+ //! }, tuple);
+ //! @endcode
+ //!
+ //! which is undeniably ugly because of the trailing `, tuple)` part
+ //! on the last line. On the other hand, taking the function as a
+ //! second argument allows one to write
+ //! @code
+ //! hana::unpack(tuple, [](auto ...args) {
+ //! use(args...);
+ //! });
+ //! @endcode
+ //!
+ //! which looks much nicer. Because of these observations, the author
+ //! of this library feels justified to use `unpack` instead of `apply`,
+ //! and to use a sane parameter order.
+ //!
+ //! [1]: http://en.cppreference.com/w/cpp/experimental/apply
+#ifdef BOOST_HANA_DOXYGEN_INVOKED
+ constexpr auto unpack = [](auto&& xs, auto&& f) -> decltype(auto) {
+ return tag-dispatched;
+ };
+#else
+ template <typename T, typename = void>
+ struct unpack_impl : unpack_impl<T, when<true>> { };
+
+ struct unpack_t {
+ template <typename Xs, typename F>
+ constexpr decltype(auto) operator()(Xs&& xs, F&& f) const;
+ };
+
+ constexpr unpack_t unpack{};
+#endif
+BOOST_HANA_NAMESPACE_END
+
+#endif // !BOOST_HANA_FWD_UNPACK_HPP