// Copyright 2017 Elias Kosunen // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // This file is a part of scnlib: // https://github.com/eliaskosunen/scnlib #ifndef SCN_TUPLE_RETURN_UTIL_H #define SCN_TUPLE_RETURN_UTIL_H #include "../util/meta.h" #include #include namespace scn { SCN_BEGIN_NAMESPACE namespace detail { // From cppreference template ::type>::value>::type* = nullptr, int = 0> constexpr auto invoke(Fn&& f, Args&&... args) noexcept( noexcept(std::mem_fn(f)(std::forward(args)...))) -> decltype(std::mem_fn(f)(std::forward(args)...)) { return std::mem_fn(f)(std::forward(args)...); } template ::type>::value>::type* = nullptr> constexpr auto invoke(Fn&& f, Args&&... args) noexcept( noexcept(std::forward(f)(std::forward(args)...))) -> decltype(std::forward(f)(std::forward(args)...)) { return std::forward(f)(std::forward(args)...); } // From Boost.mp11 template struct integer_sequence { }; // iseq_if_c template struct iseq_if_c_impl; template struct iseq_if_c_impl { using type = T; }; template struct iseq_if_c_impl { using type = E; }; template using iseq_if_c = typename iseq_if_c_impl::type; // iseq_identity template struct iseq_identity { using type = T; }; template struct append_integer_sequence; template struct append_integer_sequence, integer_sequence> { using type = integer_sequence; }; template struct make_integer_sequence_impl; template struct make_integer_sequence_impl_ { private: static_assert( N >= 0, "make_integer_sequence: N must not be negative"); static T const M = N / 2; static T const R = N % 2; using S1 = typename make_integer_sequence_impl::type; using S2 = typename append_integer_sequence::type; using S3 = typename make_integer_sequence_impl::type; using S4 = typename append_integer_sequence::type; public: using type = S4; }; template struct make_integer_sequence_impl : iseq_if_c>, iseq_if_c>, make_integer_sequence_impl_>> { }; // make_integer_sequence template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; // index_sequence template using index_sequence = integer_sequence; // make_index_sequence template using make_index_sequence = make_integer_sequence; // index_sequence_for template using index_sequence_for = make_integer_sequence; // From cppreference template constexpr auto apply_impl(F&& f, Tuple&& t, index_sequence) noexcept( noexcept(detail::invoke(std::forward(f), std::get(std::forward(t))...))) -> decltype(detail::invoke(std::forward(f), std::get(std::forward(t))...)) { return detail::invoke(std::forward(f), std::get(std::forward(t))...); } // namespace detail template constexpr auto apply(F&& f, Tuple&& t) noexcept( noexcept(detail::apply_impl( std::forward(f), std::forward(t), make_index_sequence::type>::value>{}))) -> decltype(detail::apply_impl( std::forward(f), std::forward(t), make_index_sequence::type>::value>{})) { return detail::apply_impl( std::forward(f), std::forward(t), make_index_sequence::type>::value>{}); } } // namespace detail SCN_END_NAMESPACE } // namespace scn #endif