123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /*
- * Copyright 2015-present Facebook, Inc.
- *
- * 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
- *
- * http://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.
- */
- #pragma once
- #include <limits>
- #include <tuple>
- #include <type_traits>
- // tupleRange<start, n>(tuple): select n elements starting at index start
- // in the given tuple
- // tupleRange<start>(tuple): select all elements starting at index start
- // until the end of the given tuple
- // tuplePrepend(x, tuple): return a tuple obtained by prepending x to the
- // given tuple.
- //
- // In Lisp lingo, std::get<0> is car, tupleRange<1> is cdr, and tuplePrepend
- // is cons.
- namespace folly {
- // TemplateSeq<T, ...> is a type parametrized by sizeof...(Xs) values of type
- // T. Used to destructure the values into a template parameter pack;
- // see the example in TupleSelect, below.
- template <class T, T... xs>
- struct TemplateSeq {
- template <T x>
- using Prepend = TemplateSeq<T, x, xs...>;
- };
- // TemplateRange<T, start, n>::type is
- // TemplateSeq<T, start+1, start+2, ..., start+n-1>
- template <class T, T start, T n, class Enable = void>
- struct TemplateRange;
- template <class T, T start, T n>
- struct TemplateRange<T, start, n, typename std::enable_if<(n > 0)>::type> {
- using type =
- typename TemplateRange<T, start + 1, n - 1>::type::template Prepend<
- start>;
- };
- template <class T, T start, T n>
- struct TemplateRange<T, start, n, typename std::enable_if<(n <= 0)>::type> {
- using type = TemplateSeq<T>;
- };
- // Similar to TemplateRange, given a tuple T,
- // TemplateTupleRange<T, start, n>::type is
- // TemplateSeq<size_t, start, start+1, ..., start+k-1>
- // where k = min(tuple_size<T>::value - start, n)
- // (that is, it's a TemplateSeq of at most n elements, but won't extend
- // past the end of the given tuple)
- template <
- class T,
- std::size_t start = 0,
- std::size_t n = std::numeric_limits<std::size_t>::max(),
- std::size_t size =
- std::tuple_size<typename std::remove_reference<T>::type>::value,
- class Enable = typename std::enable_if<(start <= size)>::type>
- struct TemplateTupleRange {
- using type = typename TemplateRange<
- std::size_t,
- start,
- (n <= size - start ? n : size - start)>::type;
- };
- namespace detail {
- // Helper class to select a subset of a tuple
- template <class S>
- struct TupleSelect;
- template <std::size_t... Ns>
- struct TupleSelect<TemplateSeq<std::size_t, Ns...>> {
- template <class T>
- static auto select(T&& v)
- -> decltype(std::make_tuple(std::get<Ns>(std::forward<T>(v))...)) {
- return std::make_tuple(std::get<Ns>(std::forward<T>(v))...);
- }
- };
- } // namespace detail
- // Return a tuple consisting of the elements at a range of indices.
- //
- // Use as tupleRange<start, n>(t) to return a tuple of (at most) n
- // elements starting at index start in tuple t.
- // If only start is specified (tupleRange<start>(t)), returns all elements
- // starting at index start until the end of the tuple t.
- // Won't compile if start > size of t.
- // Will return fewer elements (size - start) if start + n > size of t.
- template <
- std::size_t start = 0,
- std::size_t n = std::numeric_limits<std::size_t>::max(),
- class T,
- class Seq = typename TemplateTupleRange<T, start, n>::type>
- auto tupleRange(T&& v)
- -> decltype(detail::TupleSelect<Seq>::select(std::forward<T>(v))) {
- return detail::TupleSelect<Seq>::select(std::forward<T>(v));
- }
- // Return a tuple obtained by prepending car to the tuple cdr.
- template <class T, class U>
- auto tuplePrepend(T&& car, U&& cdr) -> decltype(std::tuple_cat(
- std::make_tuple(std::forward<T>(car)),
- std::forward<U>(cdr))) {
- return std::tuple_cat(
- std::make_tuple(std::forward<T>(car)), std::forward<U>(cdr));
- }
- } // namespace folly
|