X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FApplyTuple.h;h=3a8e14eea2255c913371d1aa3ce632cba8300d44;hb=ad8a8cb578822886334c3fb38141a2419f4bed1a;hp=a592704f080883a3a48433984e8fcb15e37d8d41;hpb=46bb1ed780a2ce03d856a98d4e2061d7f13b6f8c;p=folly.git diff --git a/folly/ApplyTuple.h b/folly/ApplyTuple.h index a592704f..3a8e14ee 100644 --- a/folly/ApplyTuple.h +++ b/folly/ApplyTuple.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2016 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,97 +25,65 @@ * ASSERT(x == 24); */ -#ifndef FOLLY_APPLYTUPLE_H_ -#define FOLLY_APPLYTUPLE_H_ +#pragma once -#include #include -#include +#include namespace folly { ////////////////////////////////////////////////////////////////////// namespace detail { +namespace apply_tuple { + +template +struct IndexSequence {}; + +template +struct MakeIndexSequence : MakeIndexSequence {}; + +template +struct MakeIndexSequence<0, Is...> : IndexSequence {}; + +template +using MakeIndexSequenceFromTuple = + MakeIndexSequence::type>::value>; // This is to allow using this with pointers to member functions, // where the first argument in the tuple will be the this pointer. -template F& makeCallable(F& f) { return f; } -template -auto makeCallable(R (C::*d)(A...)) -> decltype(std::mem_fn(d)) { +template +inline constexpr F&& makeCallable(F&& f) { + return std::forward(f); +} +template +inline constexpr auto makeCallable(M(C::*d)) -> decltype(std::mem_fn(d)) { return std::mem_fn(d); } -template -struct DerefSize - : std::tuple_size::type> -{}; - -template struct ExprDoUnpack { - enum { - value = sizeof...(Unpacked) < DerefSize::value - }; -}; - -template struct ExprIsUnpacked { - enum { - value = sizeof...(Unpacked) == DerefSize::value - }; -}; - -// CallTuple recursively unpacks tuple arguments so we can forward -// them into the function. -template -struct CallTuple { - template - static typename std::enable_if::value, - Ret - >::type call(const F& f, Tuple&& t, Unpacked&&... unp) { - typedef typename std::tuple_element< - sizeof...(Unpacked), - typename std::remove_reference::type - >::type ElementType; - return CallTuple::call(f, std::forward(t), - std::forward(unp)..., - std::forward(std::get(t)) - ); - } - - template - static typename std::enable_if::value, - Ret - >::type call(const F& f, Tuple&& t, Unpacked&&... unp) { - return makeCallable(f)(std::forward(unp)...); - } -}; - -// The point of this meta function is to extract the contents of the -// tuple as a parameter pack so we can pass it into std::result_of<>. -template struct ReturnValue; -template -struct ReturnValue> { - typedef typename std::result_of::type type; -}; - +template +inline constexpr auto call(F&& f, Tuple&& t, IndexSequence) + -> decltype( + std::forward(f)(std::get(std::forward(t))...)) { + return std::forward(f)(std::get(std::forward(t))...); } +} // namespace apply_tuple +} // namespace detail + ////////////////////////////////////////////////////////////////////// -template -typename detail::ReturnValue< - typename std::decay::type, - typename std::decay::type ->::type -applyTuple(const Callable& c, Tuple&& t) { - typedef typename detail::ReturnValue< - typename std::decay::type, - typename std::decay::type - >::type RetT; - return detail::CallTuple::call(c, std::forward(t)); +template +inline constexpr auto applyTuple(F&& f, Tuple&& t) + -> decltype(detail::apply_tuple::call( + detail::apply_tuple::makeCallable(std::forward(f)), + std::forward(t), + detail::apply_tuple::MakeIndexSequenceFromTuple{})) { + return detail::apply_tuple::call( + detail::apply_tuple::makeCallable(std::forward(f)), + std::forward(t), + detail::apply_tuple::MakeIndexSequenceFromTuple{}); } ////////////////////////////////////////////////////////////////////// - } - -#endif