From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- mfbt/IndexSequence.h | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 mfbt/IndexSequence.h (limited to 'mfbt/IndexSequence.h') diff --git a/mfbt/IndexSequence.h b/mfbt/IndexSequence.h new file mode 100644 index 000000000..1ccace026 --- /dev/null +++ b/mfbt/IndexSequence.h @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* A utility for expanding a tuple into a variadic argument list. + * Based on std::index_sequence. */ + +/** + * Example usage: + * + * Problem: + * + * You have a variadic function Foo: + * + * template void Foo(Args...); + * + * And a variadic function Bar, which contains a tuple: + * + * template + * void Bar() { + * // ... + * Tuple t; + * } + * + * And inside Bar, you want to call Foo with the elements of the tuple as + * arguments to Foo. + * + * You want to write: + * + * Foo(Get<0>(t), Get<1>(t), ..., Get(t)) + * + * but you can't literally write that, because N is different for different + * instantiations of Bar. + * + * Solution: + * + * Write a helper function which takes the tuple, and an index sequence + * containing indices corresponding to the tuple indices. + * + * template + * void Helper(const Tuple& t, IndexSequence) + * { + * Foo(Get(t)...); + * } + * + * Assuming 'Indices...' are 0, 1, ..., N - 1, where N is the size of the + * tuple, pack expansion will expand the pack 'Get(t)...' to + * 'Get<0>(t), Get<1>(t), ..., Get(t)'. + * + * Finally, call the helper, creating the index sequence to pass in like so: + * + * template + * void Bar() { + * // ... + * Tuple t; + * Helper(t, typename IndexSequenceFor::Type()); + * } + */ + +#ifndef mozilla_IndexSequence_h +#define mozilla_IndexSequence_h + +#include "mozilla/Attributes.h" + +#include + +namespace mozilla { + +/** + * Represents a compile-time sequence of integer indices. + */ +template +struct IndexSequence +{ + static constexpr size_t Size() { return sizeof...(Indices); } +}; + +namespace detail { + +// Helpers used by MakeIndexSequence. + +template +struct IndexTuple +{ + typedef IndexTuple Next; +}; + +// Builds IndexTuple<0, 1, ..., N - 1>. +template +struct BuildIndexTuple +{ + typedef typename BuildIndexTuple::Type::Next Type; +}; + +template<> +struct BuildIndexTuple<0> +{ + typedef IndexTuple<> Type; +}; + +template +struct MakeIndexSequenceImpl; + +template +struct MakeIndexSequenceImpl> +{ + typedef IndexSequence Type; +}; + +} // namespace detail + +/** + * A utility for building an IndexSequence of consecutive indices. + * MakeIndexSequence::Type evaluates to IndexSequence<0, 1, .., N - 1>. + * Note: unlike std::make_index_sequence, this is not an alias template + * to work around bugs in MSVC 2013. + */ +template +struct MakeIndexSequence +{ + typedef typename detail::MakeIndexSequenceImpl::Type>::Type Type; +}; + +/** + * A utility for building an IndexSequence of consecutive indices + * corresponding to a variadic argument list. + * IndexSequenceFor evaluates to IndexSequence<0, 1, ..., N - 1> + * where N is the number of types in Types. + * Note: unlike std::index_sequence_for, this is not an alias template + * to work around bugs in MSVC 2013. + */ +template +struct IndexSequenceFor +{ + typedef typename MakeIndexSequence::Type Type; +}; + +} // namespace mozilla + +#endif /* mozilla_IndexSequence_h */ -- cgit v1.2.3