Commit 72cb9df4 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Give Try constructors pedantic exception specifiers

Summary: [Folly] Give Try constructors and assignment operators pedantic exception specifiers deriving from corresponding exception specifiers of element type.

Reviewed By: marshallcline

Differential Revision: D8105158

fbshipit-source-id: 3cc9aae022ddaeef3ef2b742dde8ba084bfca830
parent be791fd5
......@@ -24,7 +24,8 @@
namespace folly {
template <class T>
Try<T>::Try(Try<T>&& t) noexcept : contains_(t.contains_) {
Try<T>::Try(Try<T>&& t) noexcept(std::is_nothrow_move_constructible<T>::value)
: contains_(t.contains_) {
if (contains_ == Contains::VALUE) {
new (&value_)T(std::move(t.value_));
} else if (contains_ == Contains::EXCEPTION) {
......@@ -34,8 +35,9 @@ Try<T>::Try(Try<T>&& t) noexcept : contains_(t.contains_) {
template <class T>
template <class T2>
Try<T>::Try(typename std::enable_if<std::is_same<Unit, T2>::value,
Try<void> const&>::type t)
Try<T>::Try(typename std::enable_if<
std::is_same<Unit, T2>::value,
Try<void> const&>::type t) noexcept
: contains_(Contains::NOTHING) {
if (t.hasValue()) {
contains_ = Contains::VALUE;
......@@ -47,7 +49,8 @@ Try<T>::Try(typename std::enable_if<std::is_same<Unit, T2>::value,
}
template <class T>
Try<T>& Try<T>::operator=(Try<T>&& t) noexcept {
Try<T>& Try<T>::operator=(Try<T>&& t) noexcept(
std::is_nothrow_move_constructible<T>::value) {
if (this == &t) {
return *this;
}
......@@ -63,7 +66,8 @@ Try<T>& Try<T>::operator=(Try<T>&& t) noexcept {
}
template <class T>
Try<T>::Try(const Try<T>& t) {
Try<T>::Try(const Try<T>& t) noexcept(
std::is_nothrow_copy_constructible<T>::value) {
static_assert(
std::is_copy_constructible<T>::value,
"T must be copyable for Try<T> to be copyable");
......@@ -76,7 +80,8 @@ Try<T>::Try(const Try<T>& t) {
}
template <class T>
Try<T>& Try<T>::operator=(const Try<T>& t) {
Try<T>& Try<T>::operator=(const Try<T>& t) noexcept(
std::is_nothrow_copy_constructible<T>::value) {
static_assert(
std::is_copy_constructible<T>::value,
"T must be copyable for Try<T> to be copyable");
......
......@@ -67,41 +67,46 @@ class Try {
/*
* Construct an empty Try
*/
Try() : contains_(Contains::NOTHING) {}
Try() noexcept : contains_(Contains::NOTHING) {}
/*
* Construct a Try with a value by copy
*
* @param v The value to copy in
*/
explicit Try(const T& v) : contains_(Contains::VALUE), value_(v) {}
explicit Try(const T& v) noexcept(
std::is_nothrow_copy_constructible<T>::value)
: contains_(Contains::VALUE), value_(v) {}
/*
* Construct a Try with a value by move
*
* @param v The value to move in
*/
explicit Try(T&& v) : contains_(Contains::VALUE), value_(std::move(v)) {}
explicit Try(T&& v) noexcept(std::is_nothrow_move_constructible<T>::value)
: contains_(Contains::VALUE), value_(std::move(v)) {}
template <typename... Args>
explicit Try(in_place_t, Args&&... args) noexcept(
noexcept(::new (nullptr) T(std::declval<Args&&>()...)))
: contains_(Contains::VALUE), value_(std::forward<Args>(args)...) {}
std::is_nothrow_constructible<T, Args&&...>::value)
: contains_(Contains::VALUE), value_(static_cast<Args&&>(args)...) {}
/// Implicit conversion from Try<void> to Try<Unit>
template <class T2 = T>
/* implicit */
Try(typename std::enable_if<std::is_same<Unit, T2>::value,
Try<void> const&>::type t);
Try(typename std::enable_if<std::is_same<Unit, T2>::value, Try<void> const&>::
type t) noexcept;
/*
* Construct a Try with an exception_wrapper
*
* @param e The exception_wrapper
*/
explicit Try(exception_wrapper e)
: contains_(Contains::EXCEPTION), e_(std::move(e)) {}
explicit Try(exception_wrapper e) noexcept
: contains_(Contains::EXCEPTION),
e_(std::move(e)){}
// clang-format off
/*
* DEPRECATED
* Construct a Try with an exception_pointer
......@@ -109,19 +114,22 @@ class Try {
* @param ep The exception_pointer. Will be rethrown.
*/
[[deprecated("use Try(exception_wrapper)")]]
explicit Try(std::exception_ptr ep)
explicit Try(std::exception_ptr ep) noexcept
: contains_(Contains::EXCEPTION),
e_(exception_wrapper::from_exception_ptr(ep)) {}
// clang-format on
// Move constructor
Try(Try<T>&& t) noexcept;
Try(Try<T>&& t) noexcept(std::is_nothrow_move_constructible<T>::value);
// Move assigner
Try& operator=(Try<T>&& t) noexcept;
Try& operator=(Try<T>&& t) noexcept(
std::is_nothrow_move_constructible<T>::value);
// Copy constructor
Try(const Try& t);
Try(const Try& t) noexcept(std::is_nothrow_copy_constructible<T>::value);
// Copy assigner
Try& operator=(const Try& t);
Try& operator=(const Try& t) noexcept(
std::is_nothrow_copy_constructible<T>::value);
~Try();
......@@ -355,33 +363,37 @@ class Try<void> {
typedef void element_type;
// Construct a Try holding a successful and void result
Try() : hasValue_(true) {}
Try() noexcept : hasValue_(true) {}
/*
* Construct a Try with an exception_wrapper
*
* @param e The exception_wrapper
*/
explicit Try(exception_wrapper e) : hasValue_(false), e_(std::move(e)) {}
explicit Try(exception_wrapper e) noexcept
: hasValue_(false),
e_(std::move(e)){}
// clang-format off
/*
* DEPRECATED
* Construct a Try with an exception_pointer
*
* @param ep The exception_pointer. Will be rethrown.
*/
[[deprecated("use Try(exception_wrapper)")]]
explicit Try(std::exception_ptr ep)
[[deprecated("use Try(exception_wrapper)")]] explicit Try(
std::exception_ptr ep) noexcept
: hasValue_(false), e_(exception_wrapper::from_exception_ptr(ep)) {}
// clang-format on
// Copy assigner
Try& operator=(const Try<void>& t) {
Try& operator=(const Try<void>& t) noexcept {
hasValue_ = t.hasValue_;
e_ = t.e_;
return *this;
}
// Copy constructor
Try(const Try<void>& t) {
Try(const Try<void>& t) noexcept {
*this = t;
}
......
......@@ -37,6 +37,16 @@ class A {
int x_;
};
template <bool Nothrow>
class HasCtors {
public:
explicit HasCtors(int) noexcept(Nothrow) {}
HasCtors(HasCtors&&) noexcept(Nothrow) {}
HasCtors& operator=(HasCtors&&) noexcept(Nothrow) {}
HasCtors(HasCtors const&) noexcept(Nothrow) {}
HasCtors& operator=(HasCtors const&) noexcept(Nothrow) {}
};
class MoveConstructOnly {
public:
MoveConstructOnly() = default;
......@@ -71,6 +81,46 @@ TEST(Try, in_place_nested) {
EXPECT_EQ(5, t_t_a.value().value().x());
}
TEST(Try, nothrow) {
using F = HasCtors<false>;
using T = HasCtors<true>;
// default ctor
EXPECT_TRUE(std::is_nothrow_default_constructible<Try<F>>::value);
EXPECT_TRUE(std::is_nothrow_default_constructible<Try<T>>::value);
EXPECT_TRUE(std::is_nothrow_default_constructible<Try<void>>::value);
// inner ctor - no void
EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, F&&>::value));
EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, T&&>::value));
EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, F const&>::value));
EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, T const&>::value));
// emplacing ctor - no void
EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, in_place_t, int>::value));
EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, in_place_t, int>::value));
// copy/move ctor/assign
EXPECT_TRUE(std::is_nothrow_constructible<Try<void>>::value);
EXPECT_FALSE(std::is_nothrow_move_constructible<Try<F>>::value);
EXPECT_TRUE(std::is_nothrow_move_constructible<Try<T>>::value);
EXPECT_TRUE(std::is_nothrow_move_constructible<Try<void>>::value);
EXPECT_FALSE(std::is_nothrow_move_assignable<Try<F>>::value);
EXPECT_TRUE(std::is_nothrow_move_assignable<Try<T>>::value);
EXPECT_TRUE(std::is_nothrow_move_assignable<Try<void>>::value);
EXPECT_FALSE(std::is_nothrow_copy_constructible<Try<F>>::value);
EXPECT_TRUE(std::is_nothrow_copy_constructible<Try<T>>::value);
EXPECT_TRUE(std::is_nothrow_copy_constructible<Try<void>>::value);
EXPECT_FALSE(std::is_nothrow_copy_assignable<Try<F>>::value);
EXPECT_TRUE(std::is_nothrow_copy_assignable<Try<T>>::value);
EXPECT_TRUE(std::is_nothrow_copy_assignable<Try<void>>::value);
// conversion ctor - void to unit
EXPECT_TRUE((std::is_nothrow_constructible<Try<Unit>, Try<void>&&>::value));
EXPECT_TRUE(
(std::is_nothrow_constructible<Try<Unit>, Try<void> const&>::value));
}
TEST(Try, MoveDereference) {
auto ptr = std::make_unique<int>(1);
auto t = Try<std::unique_ptr<int>>{std::move(ptr)};
......
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