@@ -158,7 +158,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Construct with a copy of @p __value as the contained object.
template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
- typename _Mgr = _Manager<_Tp>>
+ typename _Mgr = _Manager<_Tp>,
+ typename enable_if<is_constructible<_Tp, _ValueType&&>::value,
+ bool>::type = true>
any(_ValueType&& __value)
: _M_manager(&_Mgr::_S_manage)
{
@@ -167,6 +169,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"The contained object must be CopyConstructible");
}
+ /// Construct with a copy of @p __value as the contained object.
+ template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
+ typename _Mgr = _Manager<_Tp>,
+ typename enable_if<!is_constructible<_Tp, _ValueType&&>::value,
+ bool>::type = false>
+ any(_ValueType&& __value)
+ : _M_manager(&_Mgr::_S_manage)
+ {
+ _Mgr::_S_create(_M_storage, __value);
+ static_assert(is_copy_constructible<_Tp>::value,
+ "The contained object must be CopyConstructible");
+ }
+
/// Destructor, calls @c clear()
~any() { clear(); }
@@ -377,7 +392,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_bad_any_cast();
}
- template<typename _ValueType>
+ template<typename _ValueType,
+ typename enable_if<!is_move_constructible<_ValueType>::value
+ || is_lvalue_reference<_ValueType>::value,
+ bool>::type = true>
inline _ValueType any_cast(any&& __any)
{
static_assert(any::__is_valid_cast<_ValueType>(),
@@ -387,6 +405,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *__p;
__throw_bad_any_cast();
}
+
+ template<typename _ValueType,
+ typename enable_if<is_move_constructible<_ValueType>::value
+ && !is_lvalue_reference<_ValueType>::value,
+ bool>::type = false>
+ inline _ValueType any_cast(any&& __any)
+ {
+ static_assert(any::__is_valid_cast<_ValueType>(),
+ "Template argument must be a reference or CopyConstructible type");
+ auto __p = any_cast<remove_reference_t<_ValueType>>(&__any);
+ if (__p)
+ return std::move(*__p);
+ __throw_bad_any_cast();
+ }
// @}
template<typename _Tp>
@@ -77,8 +77,38 @@ void test02()
}
}
+static int move_count = 0;
+
+void test03()
+{
+ struct MoveEnabled
+ {
+ MoveEnabled(MoveEnabled&&)
+ {
+ ++move_count;
+ }
+ MoveEnabled() = default;
+ MoveEnabled(const MoveEnabled&) = default;
+ };
+ MoveEnabled m;
+ MoveEnabled m2 = any_cast<MoveEnabled>(any(m));
+ VERIFY(move_count == 1);
+ MoveEnabled&& m3 = any_cast<MoveEnabled&&>(any(m));
+ VERIFY(move_count == 1);
+ struct MoveDeleted
+ {
+ MoveDeleted(MoveDeleted&&) = delete;
+ MoveDeleted() = default;
+ MoveDeleted(const MoveDeleted&) = default;
+ };
+ MoveDeleted md;
+ MoveDeleted&& md2 = any_cast<MoveDeleted>(any(std::move(md)));
+ MoveDeleted&& md3 = any_cast<MoveDeleted&&>(any(std::move(md)));
+}
+
int main()
{
test01();
test02();
+ test03();
}
@@ -26,5 +26,5 @@ void test01()
using std::experimental::any_cast;
const any y(1);
- any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 353 }
+ any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 368 }
}