PR69321 fix any_cast<T>(any*) for non-copyable T

PR libstdc++/69321
	* include/experimental/any (__any_caster): Avoid instantiating
	manager function for types that can't be stored in any.
	* include/std/any (__any_caster): Likewise.
	* testsuite/20_util/any/misc/any_cast.cc: Test non-copyable type.
	* testsuite/experimental/any/misc/any_cast.cc: Likewise.

From-SVN: r244678
This commit is contained in:
Jonathan Wakely 2017-01-20 01:22:54 +00:00 committed by Jonathan Wakely
parent 01334be4a0
commit 38a9e5a6c0
5 changed files with 47 additions and 6 deletions

View File

@ -1,5 +1,12 @@
2017-01-20 Jonathan Wakely <jwakely@redhat.com> 2017-01-20 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/69321
* include/experimental/any (__any_caster): Avoid instantiating
manager function for types that can't be stored in any.
* include/std/any (__any_caster): Likewise.
* testsuite/20_util/any/misc/any_cast.cc: Test non-copyable type.
* testsuite/experimental/any/misc/any_cast.cc: Likewise.
PR libstdc++/64903 PR libstdc++/64903
* include/bits/stl_algo.h (is_partitioned): Use increment instead of * include/bits/stl_algo.h (is_partitioned): Use increment instead of
std::advance. std::advance.

View File

@ -415,7 +415,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
void* __any_caster(const any* __any) void* __any_caster(const any* __any)
{ {
if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage) struct _None { };
using _Up = decay_t<_Tp>;
using _Vp = conditional_t<is_copy_constructible<_Up>::value, _Up, _None>;
if (__any->_M_manager != &any::_Manager<_Vp>::_S_manage)
return nullptr; return nullptr;
any::_Arg __arg; any::_Arg __arg;
__any->_M_manager(any::_Op_access, __any, &__arg); __any->_M_manager(any::_Op_access, __any, &__arg);

View File

@ -511,11 +511,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
void* __any_caster(const any* __any) void* __any_caster(const any* __any)
{ {
if (__any->_M_manager != &any::_Manager<decay_t<_Tp>>::_S_manage) if constexpr (is_copy_constructible_v<decay_t<_Tp>>)
return nullptr; {
any::_Arg __arg; if (__any->_M_manager == &any::_Manager<decay_t<_Tp>>::_S_manage)
__any->_M_manager(any::_Op_access, __any, &__arg); {
return __arg._M_obj; any::_Arg __arg;
__any->_M_manager(any::_Op_access, __any, &__arg);
return __arg._M_obj;
}
}
return nullptr;
} }
/** /**

View File

@ -118,10 +118,23 @@ void test04()
ExplicitCopy ec2{any_cast<ExplicitCopy>(std::move(x))}; ExplicitCopy ec2{any_cast<ExplicitCopy>(std::move(x))};
} }
void test05()
{
// PR libstdc++/69321
struct noncopyable {
noncopyable(noncopyable const&) = delete;
};
any a;
auto p = any_cast<noncopyable>(&a);
VERIFY( p == nullptr );
}
int main() int main()
{ {
test01(); test01();
test02(); test02();
test03(); test03();
test04(); test04();
test05();
} }

View File

@ -105,9 +105,22 @@ void test03()
MoveDeleted&& md3 = any_cast<MoveDeleted&&>(any(std::move(md))); MoveDeleted&& md3 = any_cast<MoveDeleted&&>(any(std::move(md)));
} }
void test04()
{
// PR libstdc++/69321
struct noncopyable {
noncopyable(noncopyable const&) = delete;
};
any a;
auto p = any_cast<noncopyable>(&a);
VERIFY( p == nullptr );
}
int main() int main()
{ {
test01(); test01();
test02(); test02();
test03(); test03();
test04();
} }