mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-11 06:20:25 +08:00
libstdc++: Fix constructor constraints for std::any (PR 90415)
This removes a non-standard extension to std::any which causes errors for valid code, due to recursive instantiation of a trait that isn't supposed to be in the constraints. It also removes some incorrect constraints on the in_place_type<T> constructors and emplace members, which were preventing creating a std::any object with another std::any as the contained value. 2020-04-24 Kamlesh Kumar <kamleshbhalui@gmail.com> Jonathan Wakely <jwakely@redhat.com> PR libstdc++/90415 PR libstdc++/92156 * include/std/any (any): Rename template parameters for consistency with the standard. (any::_Decay): Rename to _Decay_if_not_any. (any::any(T&&):: Remove is_constructible from constraints. Remove non-standard overload. (any::any(in_place_type_t<T>, Args&&...)) (any::any(in_place_type_t<T>, initializer_list<U>, Args&&...)) (any::emplace(Args&&...)) (any::emplace(initializer_list<U>, Args&&...)): Use decay_t instead of _Decay. * testsuite/20_util/any/cons/90415.cc: New test. * testsuite/20_util/any/cons/92156.cc: New Test. * testsuite/20_util/any/misc/any_cast_neg.cc: Make dg-error directives more robust. * testsuite/20_util/any/modifiers/92156.cc: New test.
This commit is contained in:
parent
ae962e573e
commit
d1462b0782
@ -1,3 +1,24 @@
|
||||
2020-04-24 Kamlesh Kumar <kamleshbhalui@gmail.com>
|
||||
Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/90415
|
||||
PR libstdc++/92156
|
||||
* include/std/any (any): Rename template parameters for consistency
|
||||
with the standard.
|
||||
(any::_Decay): Rename to _Decay_if_not_any.
|
||||
(any::any(T&&):: Remove is_constructible from constraints. Remove
|
||||
non-standard overload.
|
||||
(any::any(in_place_type_t<T>, Args&&...))
|
||||
(any::any(in_place_type_t<T>, initializer_list<U>, Args&&...))
|
||||
(any::emplace(Args&&...))
|
||||
(any::emplace(initializer_list<U>, Args&&...)):
|
||||
Use decay_t instead of _Decay.
|
||||
* testsuite/20_util/any/cons/90415.cc: New test.
|
||||
* testsuite/20_util/any/cons/92156.cc: New Test.
|
||||
* testsuite/20_util/any/misc/any_cast_neg.cc: Make dg-error directives
|
||||
more robust.
|
||||
* testsuite/20_util/any/modifiers/92156.cc: New test.
|
||||
|
||||
2020-04-23 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* doc/xml/manual/status_cxx2020.xml: Update C++20 status table.
|
||||
|
@ -105,8 +105,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
_Manager_internal<_Tp>,
|
||||
_Manager_external<_Tp>>;
|
||||
|
||||
template<typename _Tp, typename _Decayed = decay_t<_Tp>>
|
||||
using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;
|
||||
template<typename _Tp, typename _VTp = decay_t<_Tp>>
|
||||
using _Decay_if_not_any = enable_if_t<!is_same_v<_VTp, any>, _VTp>;
|
||||
|
||||
/// Emplace with an object created from @p __args as the contained object.
|
||||
template <typename _Tp, typename... _Args,
|
||||
@ -125,10 +125,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
void __do_emplace(initializer_list<_Up> __il, _Args&&... __args)
|
||||
{
|
||||
reset();
|
||||
_Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
|
||||
_Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
|
||||
_M_manager = &_Mgr::_S_manage;
|
||||
}
|
||||
|
||||
template <typename _Res, typename _Tp, typename... _Args>
|
||||
using __any_constructible
|
||||
= enable_if<__and_<is_copy_constructible<_Tp>,
|
||||
is_constructible<_Tp, _Args...>>::value,
|
||||
_Res>;
|
||||
|
||||
template <typename _Tp, typename... _Args>
|
||||
using __any_constructible_t
|
||||
= typename __any_constructible<bool, _Tp, _Args...>::type;
|
||||
|
||||
template<typename _VTp, typename... _Args>
|
||||
using __emplace_t
|
||||
= typename __any_constructible<_VTp&, _VTp, _Args...>::type;
|
||||
|
||||
public:
|
||||
// construct/destruct
|
||||
|
||||
@ -165,65 +179,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
template <typename _Res, typename _Tp, typename... _Args>
|
||||
using __any_constructible =
|
||||
enable_if<__and_<is_copy_constructible<_Tp>,
|
||||
is_constructible<_Tp, _Args...>>::value,
|
||||
_Res>;
|
||||
|
||||
template <typename _Tp, typename... _Args>
|
||||
using __any_constructible_t =
|
||||
typename __any_constructible<bool, _Tp, _Args...>::type;
|
||||
|
||||
/// Construct with a copy of @p __value as the contained object.
|
||||
template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
|
||||
typename _Mgr = _Manager<_Tp>,
|
||||
__any_constructible_t<_Tp, _ValueType&&> = true,
|
||||
enable_if_t<!__is_in_place_type<_Tp>::value, bool> = true>
|
||||
any(_ValueType&& __value)
|
||||
template <typename _Tp, typename _VTp = _Decay_if_not_any<_Tp>,
|
||||
typename _Mgr = _Manager<_VTp>,
|
||||
enable_if_t<is_copy_constructible<_VTp>::value
|
||||
&& !__is_in_place_type<_VTp>::value, bool> = true>
|
||||
any(_Tp&& __value)
|
||||
: _M_manager(&_Mgr::_S_manage)
|
||||
{
|
||||
_Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value));
|
||||
}
|
||||
|
||||
/// Construct with a copy of @p __value as the contained object.
|
||||
template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
|
||||
typename _Mgr = _Manager<_Tp>,
|
||||
enable_if_t<__and_v<is_copy_constructible<_Tp>,
|
||||
__not_<is_constructible<_Tp, _ValueType&&>>,
|
||||
__not_<__is_in_place_type<_Tp>>>,
|
||||
bool> = false>
|
||||
any(_ValueType&& __value)
|
||||
: _M_manager(&_Mgr::_S_manage)
|
||||
{
|
||||
_Mgr::_S_create(_M_storage, __value);
|
||||
_Mgr::_S_create(_M_storage, std::forward<_Tp>(__value));
|
||||
}
|
||||
|
||||
/// Construct with an object created from @p __args as the contained object.
|
||||
template <typename _ValueType, typename... _Args,
|
||||
typename _Tp = _Decay<_ValueType>,
|
||||
typename _Mgr = _Manager<_Tp>,
|
||||
__any_constructible_t<_Tp, _Args&&...> = false>
|
||||
template <typename _Tp, typename... _Args, typename _VTp = decay_t<_Tp>,
|
||||
typename _Mgr = _Manager<_VTp>,
|
||||
__any_constructible_t<_VTp, _Args&&...> = false>
|
||||
explicit
|
||||
any(in_place_type_t<_ValueType>, _Args&&... __args)
|
||||
any(in_place_type_t<_Tp>, _Args&&... __args)
|
||||
: _M_manager(&_Mgr::_S_manage)
|
||||
{
|
||||
_Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
|
||||
_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 _ValueType, typename _Up, typename... _Args,
|
||||
typename _Tp = _Decay<_ValueType>,
|
||||
typename _Mgr = _Manager<_Tp>,
|
||||
__any_constructible_t<_Tp, initializer_list<_Up>,
|
||||
template <typename _Tp, typename _Up, typename... _Args,
|
||||
typename _VTp = decay_t<_Tp>, typename _Mgr = _Manager<_VTp>,
|
||||
__any_constructible_t<_VTp, initializer_list<_Up>,
|
||||
_Args&&...> = false>
|
||||
explicit
|
||||
any(in_place_type_t<_ValueType>,
|
||||
initializer_list<_Up> __il, _Args&&... __args)
|
||||
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)...);
|
||||
_Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
/// Destructor, calls @c reset()
|
||||
@ -232,7 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
// assignments
|
||||
|
||||
/// Copy the state of another object.
|
||||
any& operator=(const any& __rhs)
|
||||
any&
|
||||
operator=(const any& __rhs)
|
||||
{
|
||||
*this = any(__rhs);
|
||||
return *this;
|
||||
@ -243,7 +232,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*
|
||||
* @post @c !__rhs.has_value() (not guaranteed for other implementations)
|
||||
*/
|
||||
any& operator=(any&& __rhs) noexcept
|
||||
any&
|
||||
operator=(any&& __rhs) noexcept
|
||||
{
|
||||
if (!__rhs.has_value())
|
||||
reset();
|
||||
@ -258,40 +248,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
/// Store a copy of @p __rhs as the contained object.
|
||||
template<typename _ValueType>
|
||||
enable_if_t<is_copy_constructible<_Decay<_ValueType>>::value, any&>
|
||||
operator=(_ValueType&& __rhs)
|
||||
template<typename _Tp>
|
||||
enable_if_t<is_copy_constructible<_Decay_if_not_any<_Tp>>::value, any&>
|
||||
operator=(_Tp&& __rhs)
|
||||
{
|
||||
*this = any(std::forward<_ValueType>(__rhs));
|
||||
*this = any(std::forward<_Tp>(__rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Emplace with an object created from @p __args as the contained object.
|
||||
template <typename _ValueType, typename... _Args>
|
||||
typename __any_constructible<_Decay<_ValueType>&,
|
||||
_Decay<_ValueType>, _Args&&...>::type
|
||||
template <typename _Tp, typename... _Args>
|
||||
__emplace_t<decay_t<_Tp>, _Args...>
|
||||
emplace(_Args&&... __args)
|
||||
{
|
||||
__do_emplace<_Decay<_ValueType>>(std::forward<_Args>(__args)...);
|
||||
using _VTp = decay_t<_Tp>;
|
||||
__do_emplace<_VTp>(std::forward<_Args>(__args)...);
|
||||
any::_Arg __arg;
|
||||
this->_M_manager(any::_Op_access, this, &__arg);
|
||||
return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
|
||||
return *static_cast<_VTp*>(__arg._M_obj);
|
||||
}
|
||||
|
||||
/// Emplace with an object created from @p __il and @p __args as
|
||||
/// the contained object.
|
||||
template <typename _ValueType, typename _Up, typename... _Args>
|
||||
typename __any_constructible<_Decay<_ValueType>&,
|
||||
_Decay<_ValueType>,
|
||||
initializer_list<_Up>,
|
||||
_Args&&...>::type
|
||||
template <typename _Tp, typename _Up, typename... _Args>
|
||||
__emplace_t<decay_t<_Tp>, initializer_list<_Up>, _Args&&...>
|
||||
emplace(initializer_list<_Up> __il, _Args&&... __args)
|
||||
{
|
||||
__do_emplace<_Decay<_ValueType>, _Up>(__il,
|
||||
std::forward<_Args>(__args)...);
|
||||
using _VTp = decay_t<_Tp>;
|
||||
__do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...);
|
||||
any::_Arg __arg;
|
||||
this->_M_manager(any::_Op_access, this, &__arg);
|
||||
return *static_cast<_Decay<_ValueType>*>(__arg._M_obj);
|
||||
return *static_cast<_VTp*>(__arg._M_obj);
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
64
libstdc++-v3/testsuite/20_util/any/cons/90415.cc
Normal file
64
libstdc++-v3/testsuite/20_util/any/cons/90415.cc
Normal file
@ -0,0 +1,64 @@
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do run { target c++17 } }
|
||||
|
||||
// Copyright (C) 2020 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 copy 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 <utility>
|
||||
#include <tuple>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
// PR libstdc++/90415
|
||||
static_assert( std::is_copy_constructible<std::tuple<std::any>>::value );
|
||||
}
|
||||
|
||||
struct wrapper
|
||||
{
|
||||
wrapper() = default;
|
||||
|
||||
wrapper(const std::any& t);
|
||||
|
||||
wrapper(const wrapper& w);
|
||||
|
||||
auto& operator=(const std::any& t);
|
||||
|
||||
auto& operator=(const wrapper& w)
|
||||
{
|
||||
value = w.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::any value;
|
||||
};
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
// PR libstdc++/91630
|
||||
wrapper a, b;
|
||||
a = b;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
53
libstdc++-v3/testsuite/20_util/any/cons/92156.cc
Normal file
53
libstdc++-v3/testsuite/20_util/any/cons/92156.cc
Normal file
@ -0,0 +1,53 @@
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do run { target c++17 } }
|
||||
|
||||
// Copyright (C) 2020 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 copy 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 <utility>
|
||||
#include <tuple>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
auto a = std::any(std::in_place_type<std::any>, 5);
|
||||
VERIFY( std::any_cast<int>(std::any_cast<std::any>(a)) == 5 );
|
||||
|
||||
auto b = std::any(std::in_place_type<std::any>, {1});
|
||||
(void) std::any_cast<std::initializer_list<int>>(std::any_cast<std::any>(b));
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
std::any p = std::pair<std::any, std::any>(1, 1);
|
||||
auto pt = std::any_cast<std::pair<std::any, std::any>>(p);
|
||||
VERIFY( std::any_cast<int>(pt.first) == 1 );
|
||||
VERIFY( std::any_cast<int>(pt.second) == 1 );
|
||||
|
||||
std::any t = std::tuple<std::any>(1);
|
||||
auto tt = std::any_cast<std::tuple<std::any>>(t);
|
||||
VERIFY( std::any_cast<int>(std::get<0>(tt)) == 1 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do compile }
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
// Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||
//
|
||||
@ -26,20 +26,22 @@ using std::any_cast;
|
||||
void test01()
|
||||
{
|
||||
const any y(1);
|
||||
any_cast<int&>(y); // { dg-error "invalid 'static_cast'" "" { target { *-*-* } } 461 }
|
||||
// { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 457 }
|
||||
any_cast<int&>(y); // { dg-error "here" }
|
||||
// { dg-error "Template argument must be constructible from a const value" "" { target { *-*-* } } 0 }
|
||||
}
|
||||
|
||||
void test02()
|
||||
{
|
||||
any y(1);
|
||||
any_cast<int&&>(y);
|
||||
// { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 483 }
|
||||
any_cast<int&&>(y); // { dg-error "here" }
|
||||
// { dg-error "Template argument must be constructible from an lvalue" "" { target { *-*-* } } 0 }
|
||||
}
|
||||
|
||||
void test03()
|
||||
{
|
||||
any y(1);
|
||||
any_cast<int&>(std::move(y)); // { dg-error "invalid 'static_cast'" "" { target { *-*-* } } 501 }
|
||||
// { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 497 }
|
||||
any_cast<int&>(std::move(y)); // { dg-error "here" }
|
||||
// { dg-error "Template argument must be constructible from an rvalue" "" { target { *-*-* } } 0 }
|
||||
}
|
||||
|
||||
// { dg-prune-output "invalid 'static_cast'" }
|
||||
|
57
libstdc++-v3/testsuite/20_util/any/modifiers/92156.cc
Normal file
57
libstdc++-v3/testsuite/20_util/any/modifiers/92156.cc
Normal file
@ -0,0 +1,57 @@
|
||||
// { dg-options "-std=gnu++17" }
|
||||
// { dg-do run { target c++17 } }
|
||||
|
||||
// Copyright (C) 2020 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 copy 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 <utility>
|
||||
#include <tuple>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
std::any a;
|
||||
a.emplace<std::any>(5);
|
||||
VERIFY( std::any_cast<int>(std::any_cast<std::any>(a)) == 5 );
|
||||
|
||||
std::any b;
|
||||
b.emplace<std::any>({1});
|
||||
(void) std::any_cast<std::initializer_list<int>>(std::any_cast<std::any>(b));
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
std::any p;
|
||||
p.emplace<std::pair<std::any, std::any>>(1, 1);
|
||||
auto pt = std::any_cast<std::pair<std::any, std::any>>(p);
|
||||
VERIFY( std::any_cast<int>(pt.first) == 1 );
|
||||
VERIFY( std::any_cast<int>(pt.second) == 1 );
|
||||
|
||||
std::any t;
|
||||
t.emplace<std::tuple<std::any>>(1);
|
||||
auto tt = std::any_cast<std::tuple<std::any>>(t);
|
||||
VERIFY( std::any_cast<int>(std::get<0>(tt)) == 1 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user