Implement N4606 optional
Summary: Adapt implementation of Library Fundamentals TS optional into an implementation of N4606 optional. - Update relational operators per http://wg21.link/P0307 - Update to requirements of http://wg21.link/P0032 - Extension: Implement trivial copy/move construction/assignment for `optional<T>` when `T` is trivially copyable. Audit P/Rs for optional LWG issues: - 2756 "C++ WP optional<T> should 'forward' T's implicit conversions" Implemented, which also resolves 2753 "Optional's constructors and assignments need constraints" (modulo my refusal to explicitly delete the move operations, which is a design error that I'm working on correcting in the 2756 P/R). - 2736 "nullopt_t insufficiently constrained" Already conforming. I've added a test ensuring that `nullopt_t` is not copy-initializable from an empty braced-init-list, which I believe is the root intent of the issue, to avoid regression. - 2740 "constexpr optional<T>::operator->" Already conforming. - 2746 "Inconsistency between requirements for emplace between optional and variant" No P/R, but note that the author's '"suggested resolution" is already implemented. - 2748 "swappable traits for optionals" Already conforming. - 2753 "Optional's constructors and assignments need constraints" Implemented. Most of the work for this patch was done by Casey Carter @ Microsoft. Thank you Casey! Reviewers: mclow.lists, CaseyCarter, EricWF Differential Revision: https://reviews.llvm.org/D22741 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@283980 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// XFAIL: libcpp-no-exceptions
|
||||
// <optional>
|
||||
|
||||
// optional<T>& operator=(const optional<T>& rhs);
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X {};
|
||||
|
||||
struct Y
|
||||
{
|
||||
Y() = default;
|
||||
Y& operator=(const Y&) { return *this; }
|
||||
};
|
||||
|
||||
struct Z1
|
||||
{
|
||||
Z1() = default;
|
||||
Z1(Z1&&) = default;
|
||||
Z1(const Z1&) = default;
|
||||
Z1& operator=(Z1&&) = default;
|
||||
Z1& operator=(const Z1&) = delete;
|
||||
};
|
||||
|
||||
struct Z2
|
||||
{
|
||||
Z2() = default;
|
||||
Z2(Z2&&) = default;
|
||||
Z2(const Z2&) = delete;
|
||||
Z2& operator=(Z2&&) = default;
|
||||
Z2& operator=(const Z2&) = default;
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201402
|
||||
template <class T>
|
||||
constexpr bool
|
||||
test()
|
||||
{
|
||||
optional<T> opt;
|
||||
optional<T> opt2;
|
||||
opt = opt2;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using T = int;
|
||||
static_assert((std::is_trivially_copy_assignable<optional<T>>::value), "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(test<T>(), "");
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = X;
|
||||
static_assert((std::is_trivially_copy_assignable<optional<T>>::value), "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(test<T>(), "");
|
||||
#endif
|
||||
}
|
||||
static_assert(!(std::is_trivially_copy_assignable<optional<Y>>::value), "");
|
||||
static_assert(!(std::is_trivially_copy_assignable<optional<std::string>>::value), "");
|
||||
|
||||
static_assert(!(std::is_copy_assignable<optional<Z1>>::value), "");
|
||||
static_assert(!(std::is_copy_assignable<optional<Z2>>::value), "");
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// XFAIL: libcpp-no-exceptions
|
||||
// <optional>
|
||||
|
||||
// optional<T>& operator=(optional<T>&& rhs);
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X {};
|
||||
|
||||
struct Y
|
||||
{
|
||||
Y() = default;
|
||||
Y& operator=(Y&&) { return *this; }
|
||||
};
|
||||
|
||||
struct Z1
|
||||
{
|
||||
Z1() = default;
|
||||
Z1(Z1&&) = default;
|
||||
Z1& operator=(Z1&&) = delete;
|
||||
};
|
||||
|
||||
struct Z2
|
||||
{
|
||||
Z2() = default;
|
||||
Z2(Z2&&) = delete;
|
||||
Z2& operator=(Z2&&) = default;
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201402
|
||||
template <class T>
|
||||
constexpr bool
|
||||
test()
|
||||
{
|
||||
optional<T> opt;
|
||||
optional<T> opt2;
|
||||
opt = std::move(opt2);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using T = int;
|
||||
static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(test<T>(), "");
|
||||
#endif
|
||||
}
|
||||
{
|
||||
using T = X;
|
||||
static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
|
||||
#if __cplusplus >= 201402
|
||||
static_assert(test<T>(), "");
|
||||
#endif
|
||||
}
|
||||
static_assert(!(std::is_trivially_move_assignable<optional<Y>>::value), "");
|
||||
static_assert(!(std::is_trivially_move_assignable<optional<std::string>>::value), "");
|
||||
|
||||
static_assert(!(std::is_move_assignable<optional<Z1>>::value), "");
|
||||
static_assert(!(std::is_move_assignable<optional<Z2>>::value), "");
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// XFAIL: libcpp-no-exceptions
|
||||
// <optional>
|
||||
|
||||
// optional(const optional<T>& rhs);
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X {};
|
||||
|
||||
struct Y
|
||||
{
|
||||
Y() = default;
|
||||
Y(const Y&) {}
|
||||
};
|
||||
|
||||
struct Z
|
||||
{
|
||||
Z() = default;
|
||||
Z(Z&&) = delete;
|
||||
Z(const Z&) = delete;
|
||||
Z& operator=(Z&&) = delete;
|
||||
Z& operator=(const Z&) = delete;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using T = int;
|
||||
static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
|
||||
constexpr optional<T> opt;
|
||||
constexpr optional<T> opt2 = opt;
|
||||
(void)opt2;
|
||||
}
|
||||
{
|
||||
using T = X;
|
||||
static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
|
||||
constexpr optional<T> opt;
|
||||
constexpr optional<T> opt2 = opt;
|
||||
(void)opt2;
|
||||
}
|
||||
static_assert(!(std::is_trivially_copy_constructible<optional<Y>>::value), "");
|
||||
static_assert(!(std::is_trivially_copy_constructible<optional<std::string>>::value), "");
|
||||
|
||||
static_assert(!(std::is_copy_constructible<optional<Z>>::value), "");
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// XFAIL: libcpp-no-exceptions
|
||||
// <optional>
|
||||
|
||||
// optional(optional<T>&& rhs);
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
using std::optional;
|
||||
|
||||
struct X {};
|
||||
|
||||
struct Y
|
||||
{
|
||||
Y() = default;
|
||||
Y(Y&&) {}
|
||||
};
|
||||
|
||||
struct Z
|
||||
{
|
||||
Z() = default;
|
||||
Z(Z&&) = delete;
|
||||
Z(const Z&) = delete;
|
||||
Z& operator=(Z&&) = delete;
|
||||
Z& operator=(const Z&) = delete;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using T = int;
|
||||
static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
|
||||
constexpr optional<T> opt;
|
||||
constexpr optional<T> opt2 = std::move(opt);
|
||||
(void)opt2;
|
||||
}
|
||||
{
|
||||
using T = X;
|
||||
static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
|
||||
constexpr optional<T> opt;
|
||||
constexpr optional<T> opt2 = std::move(opt);
|
||||
(void)opt2;
|
||||
}
|
||||
static_assert(!(std::is_trivially_move_constructible<optional<Y>>::value), "");
|
||||
static_assert(!(std::is_trivially_move_constructible<optional<std::string>>::value), "");
|
||||
|
||||
static_assert(!(std::is_move_constructible<optional<Z>>::value), "");
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
// <optional>
|
||||
|
||||
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "archetypes.hpp"
|
||||
|
||||
template <class T>
|
||||
struct SpecialMemberTest {
|
||||
using O = std::optional<T>;
|
||||
|
||||
template <template <class> class TestMF>
|
||||
static constexpr bool check_same() {
|
||||
return TestMF<O>::value == TestMF<T>::value;
|
||||
}
|
||||
|
||||
// Test that optional inherits the correct trivial/non-trivial members
|
||||
static_assert(check_same<std::is_trivially_destructible>(), "");
|
||||
static_assert(check_same<std::is_trivially_copyable>(), "");
|
||||
};
|
||||
|
||||
template <class ...Args> static void sink(Args&&...) {}
|
||||
|
||||
template <class ...TestTypes>
|
||||
struct DoTestsMetafunction {
|
||||
DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
|
||||
};
|
||||
|
||||
struct TrivialMoveNonTrivialCopy {
|
||||
TrivialMoveNonTrivialCopy() = default;
|
||||
TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
|
||||
TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
|
||||
TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
|
||||
TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
|
||||
};
|
||||
|
||||
struct TrivialCopyNonTrivialMove {
|
||||
TrivialCopyNonTrivialMove() = default;
|
||||
TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
|
||||
TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
|
||||
TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
|
||||
TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
sink(
|
||||
ImplicitTypes::ApplyTypes<DoTestsMetafunction>{},
|
||||
ExplicitTypes::ApplyTypes<DoTestsMetafunction>{},
|
||||
NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{},
|
||||
NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{},
|
||||
DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{}
|
||||
);
|
||||
}
|
||||
20
test/libcxx/utilities/optional/version.pass.cpp
Normal file
20
test/libcxx/utilities/optional/version.pass.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <optional>
|
||||
|
||||
#include <optional>
|
||||
|
||||
#ifndef _LIBCPP_VERSION
|
||||
#error _LIBCPP_VERSION not defined
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user