From eaf6e90eb308ab82b4bc058a7ae2d55380a65fdd Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Mon, 11 May 2015 17:23:33 -0400 Subject: [PATCH] Bug 1163329 - Add a utility for expanding a tuple into a variadic argument list to MFBT. r=froydnj --HG-- extra : rebase_source : e6aaf87a75bfcbebdbd93824a0927ac89a9d2f78 extra : source : d2ccca76a74b83715edefb4414661f4a265021a3 --- mfbt/IndexSequence.h | 143 +++++++++++++++++++++++++++++++++++++++++++ mfbt/moz.build | 1 + 2 files changed, 144 insertions(+) create mode 100644 mfbt/IndexSequence.h diff --git a/mfbt/IndexSequence.h b/mfbt/IndexSequence.h new file mode 100644 index 000000000000..83abdc0a4ace --- /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 MOZ_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 */ diff --git a/mfbt/moz.build b/mfbt/moz.build index e1c2c35fc382..1f358423b910 100644 --- a/mfbt/moz.build +++ b/mfbt/moz.build @@ -37,6 +37,7 @@ EXPORTS.mozilla = [ 'FloatingPoint.h', 'GuardObjects.h', 'HashFunctions.h', + 'IndexSequence.h', 'IntegerPrintfMacros.h', 'IntegerRange.h', 'IntegerTypeTraits.h',