Commit 374d408b authored by Aaryaman Sagar's avatar Aaryaman Sagar Committed by Facebook Github Bot

unwrapTryTuple only accepted rvalue tuple types

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
parent de75bdc4
......@@ -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 \
......
......@@ -16,8 +16,10 @@
#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
......@@ -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
......
/*
* 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
......@@ -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);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment