Commit 25a69162 by Ville Voutilainen Committed by Ville Voutilainen

Implement P0032R3, Homogeneous interface for variant, any and optional,

	for the parts concerning any and optional.
	* include/std/any (_Storage()): Make constexpr and have it
	initialize _M_ptr.
	(any()): Make constexpr.
	(any(const any&)): Adjust.
	(any(any&&)): Likewise.
	(__any_constructible_t): New.
	(any(_ValueType&&)): Constrain.
	(any(in_place_type_t<_Tp>, _Args&&...)): New.
	(any(in_place_type_t<_Tp>, initializer_list<_Up>, _Args&&...)):
	Likewise.
	(~any()): Adjust.
	(operator=(const any&)): Likewise.
	(operator=(any&&)): Likewise.
	(operator=(_ValueType&&)): Constrain.
	(emplace(_Args&&...)): New.
	(emplace(initializer_list<_Up>, _Args&&...)): Likewise.
	(clear()): Remove.
	(reset()): New.
	(swap(any&)): Adjust.
	(empty()): Remove.
	(has_value()): New.
	(type()): Adjust.
	(_Manager_internal::_S_create(_Storage&, _Args&&...)): New.
	(_Manager_external::_S_create(_Storage&, _Args&&...)): Likewise.
	(make_any(_Args&&...)): Likewise.
	(make_any(initializer_list<_Up>, _Args&&...)): Likewise.
	* include/std/optional (in_place_t, in_place): Remove.
	(bad_optional_access): Add a comment referring to LEWG 72.
	(emplace(_Args&&...)): Constrain.
	(has_value()): New.
	(reset()): Likewise.
	(make_optional(_Args&&...)): Likewise.
	(make_optional(initializer_list<_Up>, _Args&&...)): Likewise.
	* include/std/utility (in_place_tag): New.
	(__in_place, __in_place_type, __in_place_index): Likewise.
	(in_place_t, in_place_type_t, in_place_index_t): Likewise.
	(in_place(__in_place*)): Likewise.
	(in_place(__in_place_type<_Tp>*)): Likewise.
	(in_place(__in_place_index<_Idx>*)): Likewise.
	* testsuite/20_util/any/assign/1.cc: Adjust.
	* testsuite/20_util/any/assign/emplace.cc: New.
	* testsuite/20_util/any/assign/self.cc: Adjust.
	* testsuite/20_util/any/cons/1.cc: Likewise.
	* testsuite/20_util/any/cons/in_place.cc: New.
	* testsuite/20_util/any/make_any.cc: Likewise.
	* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.
	* testsuite/20_util/any/misc/swap.cc: Likewise.
	* testsuite/20_util/any/modifiers/1.cc: Likewise.
	* testsuite/20_util/any/requirements.cc: New.
	* testsuite/20_util/in_place/requirements.cc: Likewise.
	* testsuite/20_util/optional/constexpr/in_place.cc: Adjust.
	* testsuite/20_util/optional/in_place.cc: Likewise.
	* testsuite/20_util/optional/make_optional.cc: Add tests for
	the new overloads of make_optional.

From-SVN: r238329
parent c0d31471
2016-07-14 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement P0032R3, Homogeneous interface for variant, any and optional,
for the parts concerning any and optional.
* include/std/any (_Storage()): Make constexpr and have it
initialize _M_ptr.
(any()): Make constexpr.
(any(const any&)): Adjust.
(any(any&&)): Likewise.
(__any_constructible_t): New.
(any(_ValueType&&)): Constrain.
(any(in_place_type_t<_Tp>, _Args&&...)): New.
(any(in_place_type_t<_Tp>, initializer_list<_Up>, _Args&&...)):
Likewise.
(~any()): Adjust.
(operator=(const any&)): Likewise.
(operator=(any&&)): Likewise.
(operator=(_ValueType&&)): Constrain.
(emplace(_Args&&...)): New.
(emplace(initializer_list<_Up>, _Args&&...)): Likewise.
(clear()): Remove.
(reset()): New.
(swap(any&)): Adjust.
(empty()): Remove.
(has_value()): New.
(type()): Adjust.
(_Manager_internal::_S_create(_Storage&, _Args&&...)): New.
(_Manager_external::_S_create(_Storage&, _Args&&...)): Likewise.
(make_any(_Args&&...)): Likewise.
(make_any(initializer_list<_Up>, _Args&&...)): Likewise.
* include/std/optional (in_place_t, in_place): Remove.
(bad_optional_access): Add a comment referring to LEWG 72.
(emplace(_Args&&...)): Constrain.
(has_value()): New.
(reset()): Likewise.
(make_optional(_Args&&...)): Likewise.
(make_optional(initializer_list<_Up>, _Args&&...)): Likewise.
* include/std/utility (in_place_tag): New.
(__in_place, __in_place_type, __in_place_index): Likewise.
(in_place_t, in_place_type_t, in_place_index_t): Likewise.
(in_place(__in_place*)): Likewise.
(in_place(__in_place_type<_Tp>*)): Likewise.
(in_place(__in_place_index<_Idx>*)): Likewise.
* testsuite/20_util/any/assign/1.cc: Adjust.
* testsuite/20_util/any/assign/emplace.cc: New.
* testsuite/20_util/any/assign/self.cc: Adjust.
* testsuite/20_util/any/cons/1.cc: Likewise.
* testsuite/20_util/any/cons/in_place.cc: New.
* testsuite/20_util/any/make_any.cc: Likewise.
* testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.
* testsuite/20_util/any/misc/swap.cc: Likewise.
* testsuite/20_util/any/modifiers/1.cc: Likewise.
* testsuite/20_util/any/requirements.cc: New.
* testsuite/20_util/in_place/requirements.cc: Likewise.
* testsuite/20_util/optional/constexpr/in_place.cc: Adjust.
* testsuite/20_util/optional/in_place.cc: Likewise.
* testsuite/20_util/optional/make_optional.cc: Add tests for
the new overloads of make_optional.
2016-07-13 Ville Voutilainen <ville.voutilainen@gmail.com> 2016-07-13 Ville Voutilainen <ville.voutilainen@gmail.com>
Implement P0307R2, Making Optional Greater Equal Again. Implement P0307R2, Making Optional Greater Equal Again.
......
...@@ -79,8 +79,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -79,8 +79,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Holds either pointer to a heap object or the contained object itself. // Holds either pointer to a heap object or the contained object itself.
union _Storage union _Storage
{ {
// This constructor intentionally doesn't initialize anything. constexpr _Storage() : _M_ptr{nullptr} {}
_Storage() = default;
// Prevent trivial copies of this type, buffer might hold a non-POD. // Prevent trivial copies of this type, buffer might hold a non-POD.
_Storage(const _Storage&) = delete; _Storage(const _Storage&) = delete;
...@@ -113,12 +112,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -113,12 +112,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// construct/destruct // construct/destruct
/// Default constructor, creates an empty object. /// Default constructor, creates an empty object.
any() noexcept : _M_manager(nullptr) { } constexpr any() noexcept : _M_manager(nullptr) { }
/// Copy constructor, copies the state of @p __other /// Copy constructor, copies the state of @p __other
any(const any& __other) any(const any& __other)
{ {
if (__other.empty()) if (!__other.has_value())
_M_manager = nullptr; _M_manager = nullptr;
else else
{ {
...@@ -131,11 +130,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -131,11 +130,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/** /**
* @brief Move constructor, transfer the state from @p __other * @brief Move constructor, transfer the state from @p __other
* *
* @post @c __other.empty() (this postcondition is a GNU extension) * @post @c !__other.has_value() (this postcondition is a GNU extension)
*/ */
any(any&& __other) noexcept any(any&& __other) noexcept
{ {
if (__other.empty()) if (!__other.has_value())
_M_manager = nullptr; _M_manager = nullptr;
else else
{ {
...@@ -145,45 +144,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -145,45 +144,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
} }
template <typename _Tp, typename... _Args>
using __any_constructible_t =
enable_if_t<__and_<is_copy_constructible<_Tp>,
is_constructible<_Tp, _Args...>>::value,
bool>;
/// Construct with a copy of @p __value as the contained object. /// Construct with a copy of @p __value as the contained object.
template <typename _ValueType, typename _Tp = _Decay<_ValueType>, template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
typename _Mgr = _Manager<_Tp>, typename _Mgr = _Manager<_Tp>,
typename enable_if<is_constructible<_Tp, _ValueType&&>::value, __any_constructible_t<_Tp, _ValueType&&> = true>
bool>::type = true>
any(_ValueType&& __value) any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage) : _M_manager(&_Mgr::_S_manage)
{ {
_Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value)); _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value));
static_assert(is_copy_constructible<_Tp>::value,
"The contained object must be CopyConstructible");
} }
/// Construct with a copy of @p __value as the contained object. /// Construct with a copy of @p __value as the contained object.
template <typename _ValueType, typename _Tp = _Decay<_ValueType>, template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
typename _Mgr = _Manager<_Tp>, typename _Mgr = _Manager<_Tp>,
typename enable_if<!is_constructible<_Tp, _ValueType&&>::value, enable_if_t<__and_<is_copy_constructible<_Tp>,
bool>::type = false> __not_<
is_constructible<_Tp,
_ValueType&&>>>::value,
bool> = false>
any(_ValueType&& __value) any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage) : _M_manager(&_Mgr::_S_manage)
{ {
_Mgr::_S_create(_M_storage, __value); _Mgr::_S_create(_M_storage, __value);
static_assert(is_copy_constructible<_Tp>::value,
"The contained object must be CopyConstructible");
} }
/// Destructor, calls @c clear() /// Construct with an object created from @p __args as the contained object.
~any() { clear(); } template <typename _Tp, typename... _Args,
typename _Mgr = _Manager<_Tp>,
__any_constructible_t<_Tp, _Args&&...> = false>
any(in_place_type_t<_Tp>, _Args&&... __args)
: _M_manager(&_Mgr::_S_manage)
{
_Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
}
/// Construct with an object created from @p __il and @p __args as
/// the contained object.
template <typename _Tp, typename _Up, typename... _Args,
typename _Mgr = _Manager<_Tp>,
__any_constructible_t<_Tp, initializer_list<_Up>,
_Args&&...> = false>
any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args)
: _M_manager(&_Mgr::_S_manage)
{
_Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
}
/// Destructor, calls @c reset()
~any() { reset(); }
// assignments // assignments
/// Copy the state of another object. /// Copy the state of another object.
any& operator=(const any& __rhs) any& operator=(const any& __rhs)
{ {
if (__rhs.empty()) if (!__rhs.has_value())
clear(); reset();
else if (this != &__rhs) else if (this != &__rhs)
{ {
if (!empty()) if (has_value())
_M_manager(_Op_destroy, this, nullptr); _M_manager(_Op_destroy, this, nullptr);
_Arg __arg; _Arg __arg;
__arg._M_any = this; __arg._M_any = this;
...@@ -195,15 +220,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -195,15 +220,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/** /**
* @brief Move assignment operator * @brief Move assignment operator
* *
* @post @c __rhs.empty() (not guaranteed for other implementations) * @post @c !__rhs.has_value() (not guaranteed for other implementations)
*/ */
any& operator=(any&& __rhs) noexcept any& operator=(any&& __rhs) noexcept
{ {
if (__rhs.empty()) if (!__rhs.has_value())
clear(); reset();
else if (this != &__rhs) else if (this != &__rhs)
{ {
if (!empty()) if (has_value())
_M_manager(_Op_destroy, this, nullptr); _M_manager(_Op_destroy, this, nullptr);
_Arg __arg; _Arg __arg;
__arg._M_any = this; __arg._M_any = this;
...@@ -214,19 +239,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -214,19 +239,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Store a copy of @p __rhs as the contained object. /// Store a copy of @p __rhs as the contained object.
template<typename _ValueType> template<typename _ValueType>
enable_if_t<!is_same<any, decay_t<_ValueType>>::value, any&> enable_if_t<__and_<__not_<is_same<any, decay_t<_ValueType>>>,
is_copy_constructible<_ValueType>>::value, any&>
operator=(_ValueType&& __rhs) operator=(_ValueType&& __rhs)
{ {
*this = any(std::forward<_ValueType>(__rhs)); *this = any(std::forward<_ValueType>(__rhs));
return *this; return *this;
} }
/// Emplace with an object created from @p __args as the contained object.
template <typename _Tp, typename... _Args,
typename _Mgr = _Manager<_Tp>,
__any_constructible_t<_Tp, _Args&&...> = false>
void emplace(_Args&&... __args)
{
reset();
_M_manager = &_Mgr::_S_manage;
_Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
}
/// Emplace with an object created from @p __il and @p __args as
/// the contained object.
template <typename _Tp, typename _Up, typename... _Args,
typename _Mgr = _Manager<_Tp>,
__any_constructible_t<_Tp, initializer_list<_Up>,
_Args&&...> = false>
void emplace(initializer_list<_Up> __il, _Args&&... __args)
{
reset();
_M_manager = &_Mgr::_S_manage;
_Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
}
// modifiers // modifiers
/// If not empty, destroy the contained object. /// If not empty, destroy the contained object.
void clear() noexcept void reset() noexcept
{ {
if (!empty()) if (has_value())
{ {
_M_manager(_Op_destroy, this, nullptr); _M_manager(_Op_destroy, this, nullptr);
_M_manager = nullptr; _M_manager = nullptr;
...@@ -236,10 +286,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -236,10 +286,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Exchange state with another object. /// Exchange state with another object.
void swap(any& __rhs) noexcept void swap(any& __rhs) noexcept
{ {
if (empty() && __rhs.empty()) if (!has_value() && !__rhs.has_value())
return; return;
if (!empty() && !__rhs.empty()) if (has_value() && __rhs.has_value())
{ {
if (this == &__rhs) if (this == &__rhs)
return; return;
...@@ -255,8 +305,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -255,8 +305,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
else else
{ {
any* __empty = empty() ? this : &__rhs; any* __empty = !has_value() ? this : &__rhs;
any* __full = empty() ? &__rhs : this; any* __full = !has_value() ? &__rhs : this;
_Arg __arg; _Arg __arg;
__arg._M_any = __empty; __arg._M_any = __empty;
__full->_M_manager(_Op_xfer, __full, &__arg); __full->_M_manager(_Op_xfer, __full, &__arg);
...@@ -266,13 +316,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -266,13 +316,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// observers // observers
/// Reports whether there is a contained object or not. /// Reports whether there is a contained object or not.
bool empty() const noexcept { return _M_manager == nullptr; } bool has_value() const noexcept { return _M_manager != nullptr; }
#if __cpp_rtti #if __cpp_rtti
/// The @c typeid of the contained object, or @c typeid(void) if empty. /// The @c typeid of the contained object, or @c typeid(void) if empty.
const type_info& type() const noexcept const type_info& type() const noexcept
{ {
if (empty()) if (!has_value())
return typeid(void); return typeid(void);
_Arg __arg; _Arg __arg;
_M_manager(_Op_get_type_info, this, &__arg); _M_manager(_Op_get_type_info, this, &__arg);
...@@ -316,6 +366,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -316,6 +366,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void* __addr = &__storage._M_buffer; void* __addr = &__storage._M_buffer;
::new (__addr) _Tp(std::forward<_Up>(__value)); ::new (__addr) _Tp(std::forward<_Up>(__value));
} }
template<typename... _Args>
static void
_S_create(_Storage& __storage, _Args&&... __args)
{
void* __addr = &__storage._M_buffer;
::new (__addr) _Tp(std::forward<_Args>(__args)...);
}
}; };
// Manage external contained object. // Manage external contained object.
...@@ -331,12 +389,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -331,12 +389,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ {
__storage._M_ptr = new _Tp(std::forward<_Up>(__value)); __storage._M_ptr = new _Tp(std::forward<_Up>(__value));
} }
template<typename... _Args>
static void
_S_create(_Storage& __storage, _Args&&... __args)
{
__storage._M_ptr = new _Tp(std::forward<_Args>(__args)...);
}
}; };
}; };
/// Exchange the states of two @c any objects. /// Exchange the states of two @c any objects.
inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); } inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
/// Create an any holding a @c _Tp constructed from @c __args.
template <typename _Tp, typename... _Args>
any make_any(_Args&&... __args)
{
return any(in_place<_Tp>, std::forward<_Args>(__args)...);
}
/// Create an any holding a @c _Tp constructed from @c __il and @c __args.
template <typename _Tp, typename _Up, typename... _Args>
any make_any(initializer_list<_Up> __il, _Args&&... __args)
{
return any(in_place<_Tp>, __il, std::forward<_Args>(__args)...);
}
/** /**
* @brief Access the contained object. * @brief Access the contained object.
* *
......
...@@ -57,13 +57,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -57,13 +57,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
class optional; class optional;
// [X.Y.5]
/// Tag type for in-place construction.
struct in_place_t { };
/// Tag for in-place construction.
constexpr in_place_t in_place { };
// [X.Y.6] // [X.Y.6]
/// Tag type to disengage optional objects. /// Tag type to disengage optional objects.
struct nullopt_t struct nullopt_t
...@@ -91,9 +84,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -91,9 +84,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/ */
class bad_optional_access : public logic_error class bad_optional_access : public logic_error
{ {
// XXX See LEWG 72, https://issues.isocpp.org/show_bug.cgi?id=72
public: public:
bad_optional_access() : logic_error("bad optional access") { } bad_optional_access() : logic_error("bad optional access") { }
// XXX This constructor is non-standard. Should not be inline // XXX This constructor is non-standard. Should not be inline
explicit bad_optional_access(const char* __arg) : logic_error(__arg) { } explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
...@@ -641,12 +634,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -641,12 +634,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
template<typename... _Args> template<typename... _Args>
void enable_if_t<is_constructible<_Tp, _Args&&...>::value>
emplace(_Args&&... __args) emplace(_Args&&... __args)
{ {
static_assert(is_constructible<_Tp, _Args&&...>(),
"Cannot emplace value type from arguments");
this->_M_reset(); this->_M_reset();
this->_M_construct(std::forward<_Args>(__args)...); this->_M_construct(std::forward<_Args>(__args)...);
} }
...@@ -712,6 +702,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -712,6 +702,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr explicit operator bool() const noexcept constexpr explicit operator bool() const noexcept
{ return this->_M_is_engaged(); } { return this->_M_is_engaged(); }
constexpr bool has_value() const noexcept
{ return this->_M_is_engaged(); }
constexpr const _Tp& constexpr const _Tp&
value() const& value() const&
{ {
...@@ -777,6 +770,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -777,6 +770,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
? std::move(this->_M_get()) ? std::move(this->_M_get())
: static_cast<_Tp>(std::forward<_Up>(__u)); : static_cast<_Tp>(std::forward<_Up>(__u));
} }
void reset() { this->_M_reset(); }
}; };
template<typename _Tp> template<typename _Tp>
...@@ -980,6 +974,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -980,6 +974,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
make_optional(_Tp&& __t) make_optional(_Tp&& __t)
{ return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; }
template<typename _Tp, typename ..._Args>
constexpr optional<_Tp>
make_optional(_Args&&... __args)
{ return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; }
template<typename _Tp, typename _Up, typename ..._Args>
constexpr optional<_Tp>
make_optional(initializer_list<_Up> __il, _Args&&... __args)
{ return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; }
// [X.Y.12] // [X.Y.12]
template<typename _Tp> template<typename _Tp>
struct hash<optional<_Tp>> struct hash<optional<_Tp>>
......
...@@ -75,6 +75,10 @@ ...@@ -75,6 +75,10 @@
#include <bits/move.h> #include <bits/move.h>
#include <initializer_list> #include <initializer_list>
#if __cplusplus > 201402L
#include <exception>
#endif
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
...@@ -330,6 +334,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -330,6 +334,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using index_sequence_for = make_index_sequence<sizeof...(_Types)>; using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
#endif #endif
#if __cplusplus > 201402L
struct in_place_tag {
in_place_tag() = delete;
};
struct __in_place;
template<typename _Tp> struct __in_place_type;
template<size_t _Idx> struct __in_place_index;
using in_place_t = in_place_tag(&)(__in_place*);
template <class _Tp>
using in_place_type_t = in_place_tag(&)(__in_place_type<_Tp>*);
template <int _Idx>
using in_place_index_t = in_place_tag(&)(__in_place_index<_Idx>*);
inline in_place_tag in_place(__in_place*) {terminate();}
template <class _Tp>
in_place_tag in_place(__in_place_type<_Tp>*) {terminate();}
template <size_t _Idx>
in_place_tag in_place(__in_place_index<_Idx>*) {terminate();}
#endif
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace } // namespace
......
...@@ -28,12 +28,12 @@ void test01() ...@@ -28,12 +28,12 @@ void test01()
any x; any x;
any y; any y;
y = x; y = x;
VERIFY( x.empty() ); VERIFY( !x.has_value() );
VERIFY( y.empty() ); VERIFY( !y.has_value() );
y = std::move(x); y = std::move(x);
VERIFY( x.empty() ); VERIFY( !x.has_value() );
VERIFY( y.empty() ); VERIFY( !y.has_value() );
} }
void test02() void test02()
...@@ -41,16 +41,16 @@ void test02() ...@@ -41,16 +41,16 @@ void test02()
any x(1); any x(1);
any y; any y;
y = x; y = x;
VERIFY( !x.empty() ); VERIFY( x.has_value() );
VERIFY( !y.empty() ); VERIFY( y.has_value() );
x = std::move(y); x = std::move(y);
VERIFY( !x.empty() ); VERIFY( x.has_value() );
VERIFY( y.empty() ); VERIFY( !y.has_value() );
x = y; x = y;
VERIFY( x.empty() ); VERIFY( !x.has_value() );
VERIFY( y.empty() ); VERIFY( !y.has_value() );
} }
int main() int main()
......
// { dg-options "-std=gnu++17" }
// { dg-do run }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a moved_to of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <any>
#include <testsuite_hooks.h>
#include <vector>
#include <tuple>
struct combined {
std::vector<int> v;
std::tuple<int, int> t;
template<class... Args>
combined(std::initializer_list<int> il, Args&&... args)
: v(il), t(std::forward<Args>(args)...)
{
}
};
int main()
{
const int i = 42;
std::any o;
o.emplace<int>(i);
int& i2 = std::any_cast<int&>(o);
VERIFY( i2 == 42 );
VERIFY( &i2 != &i );
std::any o2;
o2.emplace<std::tuple<int, int>>(1, 2);
std::tuple<int, int>& t = std::any_cast<std::tuple<int, int>&>(o2);
VERIFY( std::get<0>(t) == 1 && std::get<1>(t) == 2);
std::any o3;
o3.emplace<std::vector<int>>({42, 666});
std::vector<int>& v = std::any_cast<std::vector<int>&>(o3);
VERIFY(v[0] == 42 && v[1] == 666);
std::any o4;
o4.emplace<combined>({42, 666});
combined& c = std::any_cast<combined&>(o4);
VERIFY(c.v[0] == 42 && c.v[1] == 666
&& std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
std::any o5;
o5.emplace<combined>({1, 2}, 3, 4);
combined& c2 = std::any_cast<combined&>(o5);
VERIFY(c2.v[0] == 1 && c2.v[1] == 2
&& std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
}
...@@ -36,13 +36,13 @@ test01() ...@@ -36,13 +36,13 @@ test01()
any a; any a;
a = a; a = a;
VERIFY( a.empty() ); VERIFY( !a.has_value() );
a = A{}; a = A{};
a = a; a = a;
VERIFY( !a.empty() ); VERIFY( a.has_value() );
a.clear(); a.reset();
VERIFY( live_objects.empty() ); VERIFY( live_objects.empty() );
} }
...@@ -57,13 +57,13 @@ test02() ...@@ -57,13 +57,13 @@ test02()
X x; X x;
std::swap(x, x); // results in "self-move-assignment" of X::a std::swap(x, x); // results in "self-move-assignment" of X::a
VERIFY( x.a.empty() ); VERIFY( !x.a.has_value() );
x.a = A{}; x.a = A{};
std::swap(x, x); // results in "self-move-assignment" of X::a std::swap(x, x); // results in "self-move-assignment" of X::a
VERIFY( !x.a.empty() ); VERIFY( x.a.has_value() );
x.a.clear(); x.a.reset();
VERIFY( live_objects.empty() ); VERIFY( live_objects.empty() );
} }
...@@ -74,13 +74,13 @@ test03() ...@@ -74,13 +74,13 @@ test03()
any a; any a;
a.swap(a); a.swap(a);
VERIFY( a.empty() ); VERIFY( !a.has_value() );
a = A{}; a = A{};
a.swap(a); a.swap(a);
VERIFY( !a.empty() ); VERIFY( a.has_value() );
a.clear(); a.reset();
VERIFY( live_objects.empty() ); VERIFY( live_objects.empty() );
} }
......
...@@ -26,29 +26,29 @@ using std::any; ...@@ -26,29 +26,29 @@ using std::any;
void test01() void test01()
{ {
any x; any x;
VERIFY( x.empty() ); VERIFY( !x.has_value() );
any y(x); any y(x);
VERIFY( x.empty() ); VERIFY( !x.has_value() );
VERIFY( y.empty() ); VERIFY( !y.has_value() );
any z(std::move(y)); any z(std::move(y));
VERIFY( y.empty() ); VERIFY( !y.has_value() );
VERIFY( z.empty() ); VERIFY( !z.has_value() );
} }
void test02() void test02()
{ {
any x(1); any x(1);
VERIFY( !x.empty() ); VERIFY( x.has_value() );
any y(x); any y(x);
VERIFY( !x.empty() ); VERIFY( x.has_value() );
VERIFY( !y.empty() ); VERIFY( y.has_value() );
any z(std::move(y)); any z(std::move(y));
VERIFY( y.empty() ); VERIFY( !y.has_value() );
VERIFY( !z.empty() ); VERIFY( z.has_value() );
} }
int main() int main()
......
// { dg-options "-std=gnu++17" }
// { dg-do run }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a moved_to of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <any>
#include <testsuite_hooks.h>
#include <vector>
#include <tuple>
struct combined {
std::vector<int> v;
std::tuple<int, int> t;
template<class... Args>
combined(std::initializer_list<int> il, Args&&... args)
: v(il), t(std::forward<Args>(args)...)
{
}
};
int main()
{
const int i = 42;
std::any o(std::in_place<int>, i);
int& i2 = std::any_cast<int&>(o);
VERIFY( i2 == 42 );
VERIFY( &i2 != &i );
std::any o2(std::in_place<std::tuple<int, int>>, 1, 2);
std::tuple<int, int>& t = std::any_cast<std::tuple<int, int>&>(o2);
VERIFY( std::get<0>(t) == 1 && std::get<1>(t) == 2);
std::any o3(std::in_place<std::vector<int>>, {42, 666});
std::vector<int>& v = std::any_cast<std::vector<int>&>(o3);
VERIFY(v[0] == 42 && v[1] == 666);
std::any o4(std::in_place<combined>, {42, 666});
combined& c = std::any_cast<combined&>(o4);
VERIFY(c.v[0] == 42 && c.v[1] == 666
&& std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
std::any o5(std::in_place<combined>, {1, 2}, 3, 4);
combined& c2 = std::any_cast<combined&>(o5);
VERIFY(c2.v[0] == 1 && c2.v[1] == 2
&& std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
}
// { dg-options "-std=gnu++17" }
// { dg-do run }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a moved_to of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <any>
#include <testsuite_hooks.h>
#include <vector>
#include <tuple>
struct combined {
std::vector<int> v;
std::tuple<int, int> t;
template<class... Args>
combined(std::initializer_list<int> il, Args&&... args)
: v(il), t(std::forward<Args>(args)...)
{
}
};
int main()
{
const int i = 42;
auto o = std::make_any<int>(i);
int& i2 = std::any_cast<int&>(o);
VERIFY( i2 == 42 );
VERIFY( &i2 != &i );
auto o2 = std::make_any<std::tuple<int, int>>(1, 2);
std::tuple<int, int>& t = std::any_cast<std::tuple<int, int>&>(o2);
VERIFY( std::get<0>(t) == 1 && std::get<1>(t) == 2);
auto o3 = std::make_any<std::vector<int>>({42, 666});
std::vector<int>& v = std::any_cast<std::vector<int>&>(o3);
VERIFY(v[0] == 42 && v[1] == 666);
auto o4 = std::make_any<combined>({42, 666});
combined& c = std::any_cast<combined&>(o4);
VERIFY(c.v[0] == 42 && c.v[1] == 666
&& std::get<0>(c.t) == 0 && std::get<1>(c.t) == 0 );
auto o5 = std::make_any<combined>({1, 2}, 3, 4);
combined& c2 = std::any_cast<combined&>(o5);
VERIFY(c2.v[0] == 1 && c2.v[1] == 2
&& std::get<0>(c2.t) == 3 && std::get<1>(c2.t) == 4 );
}
...@@ -26,5 +26,5 @@ void test01() ...@@ -26,5 +26,5 @@ void test01()
using std::any_cast; using std::any_cast;
const any y(1); const any y(1);
any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 357 } any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 435 }
} }
...@@ -28,8 +28,8 @@ void test01() ...@@ -28,8 +28,8 @@ void test01()
any x(1); any x(1);
any y; any y;
swap(x, y); swap(x, y);
VERIFY( x.empty() ); VERIFY( !x.has_value() );
VERIFY( !y.empty() ); VERIFY( y.has_value() );
} }
int main() int main()
......
...@@ -28,14 +28,14 @@ void test01() ...@@ -28,14 +28,14 @@ void test01()
any x(1); any x(1);
any y; any y;
x.swap(y); x.swap(y);
VERIFY( x.empty() ); VERIFY( !x.has_value() );
VERIFY( !y.empty() ); VERIFY( y.has_value() );
x.swap(y); x.swap(y);
VERIFY( !x.empty() ); VERIFY( x.has_value() );
VERIFY( y.empty() ); VERIFY( !y.has_value() );
x.clear(); x.reset();
VERIFY( x.empty() ); VERIFY( !x.has_value() );
} }
int main() int main()
......
// { dg-options "-std=gnu++17" }
// { dg-do compile }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a moved_to of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <any>
#include <testsuite_hooks.h>
#include <memory>
using std::any;
using std::unique_ptr;
static_assert(std::is_assignable<any&, int>::value);
static_assert(!std::is_assignable<any&, unique_ptr<int>>::value);
static_assert(std::is_constructible<any, int>::value);
static_assert(!std::is_constructible<any, unique_ptr<int>>::value);
// { dg-options "-std=gnu++17" }
// { dg-do compile }
// Copyright (C) 2016 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a moved_to of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <utility>
#include <type_traits>
#include <testsuite_hooks.h>
using std::in_place_t;
using std::in_place_type_t;
using std::in_place_index_t;
float f(in_place_type_t<float>);
double f(in_place_type_t<double>);
char f(in_place_index_t<0>);
unsigned int f(in_place_index_t<1>);
int f(in_place_t);
static_assert(std::is_same<decltype(f(in_place_t(std::in_place))), int>::value);
static_assert(std::is_same<decltype(f(std::in_place<float>)), float>::value);
static_assert(std::is_same<decltype(f(std::in_place<double>)), double>::value);
static_assert(std::is_same<decltype(f(std::in_place<0>)), char>::value);
static_assert(std::is_same<decltype(f(std::in_place<1>)), unsigned int>::value);
template <class T, class... Args> float h(in_place_type_t<T>, Args&&...);
template <size_t N, class... Args> int h(in_place_index_t<N>, Args&&...);
template <class T> double h(in_place_t, T&&);
static_assert(std::is_same<decltype(h(std::in_place, 1)), double>::value);
static_assert(std::is_same<decltype(h(std::in_place<float>, 1)), float>::value);
static_assert(std::is_same<decltype(h(std::in_place<0>, 1)), int>::value);
...@@ -24,9 +24,6 @@ ...@@ -24,9 +24,6 @@
int main() int main()
{ {
// [20.5.5] In-place construction // [20.5.5] In-place construction
static_assert( std::is_same<decltype(std::in_place), const std::in_place_t>(), "" );
static_assert( std::is_empty<std::in_place_t>(), "" );
{ {
constexpr std::optional<int> o { std::in_place }; constexpr std::optional<int> o { std::in_place };
static_assert( o, "" ); static_assert( o, "" );
......
...@@ -26,9 +26,6 @@ ...@@ -26,9 +26,6 @@
int main() int main()
{ {
// [20.5.5] In-place construction // [20.5.5] In-place construction
static_assert( std::is_same<decltype(std::in_place), const std::in_place_t>(), "" );
static_assert( std::is_empty<std::in_place_t>(), "" );
{ {
std::optional<int> o { std::in_place }; std::optional<int> o { std::in_place };
VERIFY( o ); VERIFY( o );
......
...@@ -20,6 +20,18 @@ ...@@ -20,6 +20,18 @@
#include <optional> #include <optional>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
#include <vector>
#include <tuple>
struct combined {
std::vector<int> v;
std::tuple<int, int> t;
template<class... Args>
combined(std::initializer_list<int> il, Args&&... args)
: v(il), t(std::forward<Args>(args)...)
{
}
};
int main() int main()
{ {
...@@ -28,4 +40,22 @@ int main() ...@@ -28,4 +40,22 @@ int main()
static_assert( std::is_same<decltype(o), std::optional<int>>(), "" ); static_assert( std::is_same<decltype(o), std::optional<int>>(), "" );
VERIFY( o && *o == 42 ); VERIFY( o && *o == 42 );
VERIFY( &*o != &i ); VERIFY( &*o != &i );
auto o2 = std::make_optional<std::tuple<int, int>>(1, 2);
static_assert( std::is_same<decltype(o2),
std::optional<std::tuple<int, int>>>(), "" );
VERIFY( o2 && std::get<0>(*o2) == 1 && std::get<1>(*o2) == 2);
auto o3 = std::make_optional<std::vector<int>>({42, 666});
static_assert( std::is_same<decltype(o3),
std::optional<std::vector<int>>>(), "" );
VERIFY(o3 && (*o3)[0] == 42 && (*o3)[1] == 666);
auto o4 = std::make_optional<combined>({42, 666});
static_assert( std::is_same<decltype(o4),
std::optional<combined>>(), "" );
VERIFY(o4 && (o4->v)[0] == 42 && (o4->v)[1] == 666
&& std::get<0>(o4->t) == 0 && std::get<1>(o4->t) == 0 );
auto o5 = std::make_optional<combined>({1, 2}, 3, 4);
static_assert( std::is_same<decltype(o5),
std::optional<combined>>(), "" );
VERIFY(o4 && (o5->v)[0] == 1 && (o5->v)[1] == 2
&& std::get<0>(o5->t) == 3 && std::get<1>(o5->t) == 4 );
} }
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