unwrapTryTuple only accepted rvalue tuple types
authorAaryaman Sagar <aary@instagram.com>
Thu, 24 Aug 2017 21:42:53 +0000 (14:42 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 24 Aug 2017 21:52:36 +0000 (14:52 -0700)
Summary:
unwrapTryTuple only accepted rvalue tuple types, this diff fixes that
to work with forwarding reference tuple types.

Also reduces the number of template instantiations

Reviewed By: yfeldblum

Differential Revision: D5682996

fbshipit-source-id: ee6dd2c20d8dfca33e769a98a6ca56fa96c73b72

folly/Makefile.am
folly/Try-inl.h
folly/Try.h
folly/detail/TryDetail.h [deleted file]
folly/test/TryTest.cpp

index d2ed843..18aa5bd 100644 (file)
@@ -82,7 +82,6 @@ nobase_follyinclude_HEADERS = \
        detail/SocketFastOpen.h \
        detail/StaticSingletonManager.h \
        detail/ThreadLocalDetail.h \
-       detail/TryDetail.h \
        detail/TurnSequencer.h \
        detail/UncaughtExceptionCounter.h \
        Demangle.h \
index 8adeb42..e70fce7 100644 (file)
 
 #pragma once
 
-#include <folly/detail/TryDetail.h>
+#include <folly/Utility.h>
+
 #include <stdexcept>
+#include <tuple>
 
 namespace folly {
 
@@ -163,10 +165,31 @@ makeTryWith(F&& f) {
   }
 }
 
-template <typename... Ts>
-std::tuple<Ts...> unwrapTryTuple(std::tuple<folly::Try<Ts>...>&& ts) {
-  return detail::TryTuple<Ts...>::unwrap(
-      std::forward<std::tuple<folly::Try<Ts>...>>(ts));
+namespace try_detail {
+
+/**
+ * Trait that removes the layer of Try abstractions from the passed in type
+ */
+template <typename Type>
+struct RemoveTry;
+template <template <typename...> class TupleType, typename... Types>
+struct RemoveTry<TupleType<folly::Try<Types>...>> {
+  using type = TupleType<Types...>;
+};
+
+template <std::size_t... Indices, typename Tuple>
+auto unwrapTryTupleImpl(folly::index_sequence<Indices...>, Tuple&& instance) {
+  using std::get;
+  using ReturnType = typename RemoveTry<typename std::decay<Tuple>::type>::type;
+  return ReturnType{(get<Indices>(std::forward<Tuple>(instance)).value())...};
+}
+} // namespace try_detail
+
+template <typename Tuple>
+auto unwrapTryTuple(Tuple&& instance) {
+  using TupleDecayed = typename std::decay<Tuple>::type;
+  using Seq = folly::make_index_sequence<std::tuple_size<TupleDecayed>::value>;
+  return try_detail::unwrapTryTupleImpl(Seq{}, std::forward<Tuple>(instance));
 }
 
 } // namespace folly
index 6d219a7..efcc5a9 100644 (file)
@@ -516,8 +516,14 @@ typename std::enable_if<
   Try<void>>::type
 makeTryWith(F&& f);
 
-template <typename... Ts>
-std::tuple<Ts...> unwrapTryTuple(std::tuple<folly::Try<Ts>...>&& ts);
+/**
+ * Tuple<Try<Type>...> -> std::tuple<Type...>
+ *
+ * Unwraps a tuple-like type containing a sequence of Try<Type> instances to
+ * std::tuple<Type>
+ */
+template <typename Tuple>
+auto unwrapTryTuple(Tuple&&);
 
 } // namespace folly
 
diff --git a/folly/detail/TryDetail.h b/folly/detail/TryDetail.h
deleted file mode 100644 (file)
index 3050ccd..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2017 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
-
-namespace folly {
-namespace detail {
-
-template <typename... Ts>
-struct TryTuple {
-  template <typename... Ts2>
-  static std::tuple<Ts...> unwrap(
-      std::tuple<folly::Try<Ts>...>&& o,
-      Ts2&&... ts2) {
-    static_assert(
-        sizeof...(ts2) < std::tuple_size<std::tuple<folly::Try<Ts>...>>::value,
-        "Non-templated unwrap should be used instead");
-
-    return unwrap(
-        std::move(o),
-        std::forward<Ts2>(ts2)...,
-        std::move(*std::get<sizeof...(ts2)>(o)));
-  }
-
-  static std::tuple<Ts...> unwrap(
-      std::tuple<folly::Try<Ts>...>&& /* o */,
-      Ts&&... ts) {
-    return std::tuple<Ts...>(std::forward<Ts>(ts)...);
-  }
-};
-
-} // namespace detail
-} // namespace folly
index 5fdd231..8e675f1 100644 (file)
@@ -342,3 +342,24 @@ TEST(Try, withException) {
     EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
   }
 }
+
+TEST(Try, TestUnwrapTuple) {
+  auto original = std::make_tuple(Try<int>{1}, Try<int>{2});
+  EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(original));
+  EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::copy(original)));
+  EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::as_const(original)));
+}
+
+TEST(Try, TestUnwrapPair) {
+  auto original = std::make_pair(Try<int>{1}, Try<int>{2});
+  EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(original));
+  EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::copy(original)));
+  EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::as_const(original)));
+}
+
+TEST(Try, TestUnwrapForward) {
+  using UPtr_t = std::unique_ptr<int>;
+  auto original = std::make_tuple(Try<UPtr_t>{std::make_unique<int>(1)});
+  auto unwrapped = unwrapTryTuple(std::move(original));
+  EXPECT_EQ(*std::get<0>(unwrapped), 1);
+}