1 /*!
2 @file
3 Forward declares `boost::hana::unpack`.
4 
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8  */
9 
10 #ifndef BOOST_HANA_FWD_UNPACK_HPP
11 #define BOOST_HANA_FWD_UNPACK_HPP
12 
13 #include <boost/hana/config.hpp>
14 #include <boost/hana/core/when.hpp>
15 
16 
17 namespace boost { namespace hana {
18     //! Invoke a function with the elements of a Foldable as arguments.
19     //! @ingroup group-Foldable
20     //!
21     //! Given a function and a foldable structure whose length can be known at
22     //! compile-time, `unpack` invokes the function with the contents of that
23     //! structure. In other words, `unpack(xs, f)` is equivalent to `f(x...)`,
24     //! where `x...` are the elements of the structure. The length of the
25     //! structure must be known at compile-time, because the version of `f`'s
26     //! `operator()` that will be compiled depends on the number of arguments
27     //! it is called with, which has to be known at compile-time.
28     //!
29     //! To create a function that accepts a foldable instead of variadic
30     //! arguments, see `fuse` instead.
31     //!
32     //!
33     //! @param xs
34     //! The structure to expand into the function.
35     //!
36     //! @param f
37     //! A function to be invoked as `f(x...)`, where `x...` are the elements
38     //! of the structure as-if they had been linearized with `to<tuple_tag>`.
39     //!
40     //!
41     //! Example
42     //! -------
43     //! @include example/unpack.cpp
44     //!
45     //!
46     //! Rationale: `unpack`'s name and parameter order
47     //! ----------------------------------------------
48     //! It has been suggested a couple of times that `unpack` be called
49     //! `apply` instead, and that the parameter order be reversed to match
50     //! that of the [proposed std::apply function][1]. However, the name
51     //! `apply` is already used to denote normal function application, an use
52     //! which is consistent with the Boost MPL library and with the rest of
53     //! the world, especially the functional programming community.
54     //! Furthermore, the author of this library considers the proposed
55     //! `std::apply` to have both an unfortunate name and an unfortunate
56     //! parameter order. Indeed, taking the function as the first argument
57     //! means that using `std::apply` with a lambda function looks like
58     //! @code
59     //! std::apply([](auto ...args) {
60     //!     use(args...);
61     //! }, tuple);
62     //! @endcode
63     //!
64     //! which is undeniably ugly because of the trailing `, tuple)` part
65     //! on the last line. On the other hand, taking the function as a
66     //! second argument allows one to write
67     //! @code
68     //! hana::unpack(tuple, [](auto ...args) {
69     //!     use(args...);
70     //! });
71     //! @endcode
72     //!
73     //! which looks much nicer. Because of these observations, the author
74     //! of this library feels justified to use `unpack` instead of `apply`,
75     //! and to use a sane parameter order.
76     //!
77     //! [1]: http://en.cppreference.com/w/cpp/experimental/apply
78 #ifdef BOOST_HANA_DOXYGEN_INVOKED
79     constexpr auto unpack = [](auto&& xs, auto&& f) -> decltype(auto) {
80         return tag-dispatched;
81     };
82 #else
83     template <typename T, typename = void>
84     struct unpack_impl : unpack_impl<T, when<true>> { };
85 
86     struct unpack_t {
87         template <typename Xs, typename F>
88         constexpr decltype(auto) operator()(Xs&& xs, F&& f) const;
89     };
90 
91     BOOST_HANA_INLINE_VARIABLE constexpr unpack_t unpack{};
92 #endif
93 }} // end namespace boost::hana
94 
95 #endif // !BOOST_HANA_FWD_UNPACK_HPP
96