diff options
author | Murray Cumming <murrayc@murrayc.com> | 2016-03-02 20:55:14 +0100 |
---|---|---|
committer | Murray Cumming <murrayc@murrayc.com> | 2016-03-07 10:43:09 +0100 |
commit | 1db1415169e254b626563ccbe128ee91a0fab31c (patch) | |
tree | bc98de267ca51552ba6440fec0a99cda98c0f1b0 /sigc++/tuple-utils/tuple_start.h | |
parent | 945b569c6970b44fbd22996d2b1e15eafe8e1027 (diff) | |
download | sigc++-1db1415169e254b626563ccbe128ee91a0fab31c.tar.gz |
Move all tuple_*.h files into sigc++/tuple-utils/
Diffstat (limited to 'sigc++/tuple-utils/tuple_start.h')
-rw-r--r-- | sigc++/tuple-utils/tuple_start.h | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/sigc++/tuple-utils/tuple_start.h b/sigc++/tuple-utils/tuple_start.h new file mode 100644 index 0000000..95fda2e --- /dev/null +++ b/sigc++/tuple-utils/tuple_start.h @@ -0,0 +1,80 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/ + */ + +#ifndef SIGC_TUPLE_UTILS_TUPLE_START_H +#define SIGC_TUPLE_UTILS_TUPLE_START_H + +#include <tuple> +#include <utility> + +namespace sigc { + +namespace detail { + +template <typename T, typename Seq> +struct tuple_type_start_impl; + +template <typename T, std::size_t... I> +struct tuple_type_start_impl<T, std::index_sequence<I...>> { + using type = std::tuple<typename std::tuple_element<I, T>::type...>; +}; + +} // detail namespace + +/** + * Get the type of a tuple with just the first @len items. + */ +template <typename T, std::size_t len> +struct tuple_type_start + : detail::tuple_type_start_impl<T, std::make_index_sequence<len>> {}; + +namespace detail { + +template <typename T, typename Seq> +struct tuple_start_impl; + +template <typename T, std::size_t... I> +struct tuple_start_impl<T, std::index_sequence<I...>> { + static decltype(auto) + tuple_start(T&& t) { + constexpr auto size = std::tuple_size<std::decay_t<T>>::value; + constexpr auto len = sizeof...(I); + static_assert(len <= size, "The tuple size must be less than or equal to the length."); + + using start = typename tuple_type_start<std::decay_t<T>, len>::type; + return start(std::get<I>(std::forward<T>(t))...); + } +}; + +} // detail namespace + +/** + * Get the tuple with the last @a len items of the original. + */ +template <std::size_t len, typename T> +decltype(auto) // typename tuple_type_end<T, len>::type + tuple_start(T&& t) { + //We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size<std::decay_t<T>>::value; + static_assert(len <= size, "The tuple size must be less than or equal to the length."); + + return detail::tuple_start_impl<T, std::make_index_sequence<len>>::tuple_start( + std::forward<T>(t)); +} + +} // namespace sigc; + +#endif //SIGC_TUPLE_UTILS_TUPLE_START_H |