/* * Copyright (c) Facebook, Inc. and its affiliates. * * 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 #include #include // tupleRange(tuple): select n elements starting at index start // in the given tuple // tupleRange(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 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 struct TemplateSeq { template using Prepend = TemplateSeq; }; // TemplateRange::type is // TemplateSeq template struct TemplateRange; template struct TemplateRange 0)>::type> { using type = typename TemplateRange::type::template Prepend< start>; }; template struct TemplateRange::type> { using type = TemplateSeq; }; // Similar to TemplateRange, given a tuple T, // TemplateTupleRange::type is // TemplateSeq // where k = min(tuple_size::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::max(), std::size_t size = std::tuple_size::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 struct TupleSelect; template struct TupleSelect> { template static auto select(T&& v) -> decltype(std::make_tuple(std::get(std::forward(v))...)) { return std::make_tuple(std::get(std::forward(v))...); } }; } // namespace detail // Return a tuple consisting of the elements at a range of indices. // // Use as tupleRange(t) to return a tuple of (at most) n // elements starting at index start in tuple t. // If only start is specified (tupleRange(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::max(), class T, class Seq = typename TemplateTupleRange::type> auto tupleRange(T&& v) -> decltype(detail::TupleSelect::select(std::forward(v))) { return detail::TupleSelect::select(std::forward(v)); } // Return a tuple obtained by prepending car to the tuple cdr. template auto tuplePrepend(T&& car, U&& cdr) -> decltype(std::tuple_cat( std::make_tuple(std::forward(car)), std::forward(cdr))) { return std::tuple_cat( std::make_tuple(std::forward(car)), std::forward(cdr)); } } // namespace folly