Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:58

0001 /*!
0002 @file
0003 Defines `boost::hana::arg`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_FUNCTIONAL_ARG_HPP
0011 #define BOOST_HANA_FUNCTIONAL_ARG_HPP
0012 
0013 #include <boost/hana/config.hpp>
0014 
0015 #include <cstddef>
0016 #include <type_traits>
0017 
0018 
0019 namespace boost { namespace hana {
0020     //! @ingroup group-functional
0021     //! Return the `n`th passed argument.
0022     //!
0023     //! Specifically, `arg<n>(x1, ..., xn, ..., xm)` is equivalent to `xn`.
0024     //! Note that indexing starts at 1, so `arg<1>` returns the 1st argument,
0025     //! `arg<2>` the 2nd and so on. Using `arg<0>` is an error. Passing
0026     //! less than `n` arguments to `arg<n>` is also an error.
0027     //!
0028     //!
0029     //! @tparam n
0030     //! An unsigned integer representing the argument to return. `n` must be
0031     //! positive (meaning nonzero).
0032     //!
0033     //! @param x1, ..., xm
0034     //! A variadic pack of arguments from which the `n`th one is returned.
0035     //!
0036     //!
0037     //! @internal
0038     //! ### Discussion: could `n` be dynamic?
0039     //! We could have chosen `arg` to be used like `arg(n)(x...)` instead of
0040     //! `arg<n>(x...)`. Provided all the arguments were of the same type, it
0041     //! would then be possible for `n` to only be known at runtime. However,
0042     //! we would then lose the ability to assert the in-boundedness of `n`
0043     //! statically.
0044     //!
0045     //! ### Rationale for `n` being a non-type template parameter
0046     //! I claim that the only interesting use case is with a compile-time
0047     //! `n`, which means that the usage would become `arg(int_<n>)(x...)`,
0048     //! which is more cumbersome to write than `arg<n>(x...)`. This is open
0049     //! for discussion.
0050     //! @endinternal
0051     //!
0052     //! ### Example
0053     //! @include example/functional/arg.cpp
0054 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0055     template <std::size_t n>
0056     constexpr auto arg = [](auto&& x1, ..., auto&& xm) -> decltype(auto) {
0057         return forwarded(xn);
0058     };
0059 #else
0060     template <std::size_t n, typename = void>
0061     struct arg_t;
0062 
0063     template <>
0064     struct arg_t<1> {
0065         template <typename X1, typename ...Xn>
0066         constexpr X1 operator()(X1&& x1, Xn&& ...) const
0067         { return static_cast<X1&&>(x1); }
0068     };
0069 
0070     template <>
0071     struct arg_t<2> {
0072         template <typename X1, typename X2, typename ...Xn>
0073         constexpr X2 operator()(X1&&, X2&& x2, Xn&& ...) const
0074         { return static_cast<X2&&>(x2); }
0075     };
0076 
0077     template <>
0078     struct arg_t<3> {
0079         template <typename X1, typename X2, typename X3, typename ...Xn>
0080         constexpr X3 operator()(X1&&, X2&&, X3&& x3, Xn&& ...) const
0081         { return static_cast<X3&&>(x3); }
0082     };
0083 
0084     template <>
0085     struct arg_t<4> {
0086         template <typename X1, typename X2, typename X3, typename X4, typename ...Xn>
0087         constexpr X4 operator()(X1&&, X2&&, X3&&, X4&& x4, Xn&& ...) const
0088         { return static_cast<X4&&>(x4); }
0089     };
0090 
0091     template <>
0092     struct arg_t<5> {
0093         template <typename X1, typename X2, typename X3, typename X4,
0094                   typename X5, typename ...Xn>
0095         constexpr X5 operator()(X1&&, X2&&, X3&&, X4&&, X5&& x5, Xn&& ...) const
0096         { return static_cast<X5&&>(x5); }
0097     };
0098 
0099     template <std::size_t n, typename>
0100     struct arg_t {
0101         static_assert(n > 0,
0102         "invalid usage of boost::hana::arg<n> with n == 0");
0103 
0104         template <typename X1, typename X2, typename X3, typename X4,
0105                   typename X5, typename ...Xn>
0106         constexpr decltype(auto)
0107         operator()(X1&&, X2&&, X3&&, X4&&, X5&&, Xn&& ...xn) const {
0108             static_assert(sizeof...(xn) >= n - 5,
0109             "invalid usage of boost::hana::arg<n> with too few arguments");
0110 
0111             // Since compilers will typically try to continue for a bit after
0112             // an error/static assertion, we must avoid sending the compiler
0113             // in a very long computation if n == 0.
0114             return arg_t<n == 0 ? 1 : n - 5>{}(static_cast<Xn&&>(xn)...);
0115         }
0116     };
0117 
0118     template <std::size_t n>
0119     struct arg_t<n, std::enable_if_t<(n > 25)>> {
0120         template <
0121             typename X1,  typename X2,  typename X3,  typename X4,  typename X5,
0122             typename X6,  typename X7,  typename X8,  typename X9,  typename X10,
0123             typename X11, typename X12, typename X13, typename X14, typename X15,
0124             typename X16, typename X17, typename X18, typename X19, typename X20,
0125             typename X21, typename X22, typename X23, typename X24, typename X25,
0126             typename ...Xn>
0127         constexpr decltype(auto)
0128         operator()(X1&&,  X2&&,  X3&&,  X4&&,  X5&&,
0129                    X6&&,  X7&&,  X8&&,  X9&&,  X10&&,
0130                    X11&&, X12&&, X13&&, X14&&, X15&&,
0131                    X16&&, X17&&, X18&&, X19&&, X20&&,
0132                    X21&&, X22&&, X23&&, X24&&, X25&&, Xn&& ...xn) const
0133         { return arg_t<n - 25>{}(static_cast<Xn&&>(xn)...); }
0134     };
0135 
0136     template <std::size_t n>
0137     BOOST_HANA_INLINE_VARIABLE constexpr arg_t<n> arg{};
0138 #endif
0139 }} // end namespace boost::hana
0140 
0141 #endif // !BOOST_HANA_FUNCTIONAL_ARG_HPP