libstdc++: Constrain std::make_any [PR102894]

std::make_any should be constrained so it can only be called if the
construction of the return value would be valid.

libstdc++-v3/ChangeLog:

	PR libstdc++/102894
	* include/std/any (make_any): Add SFINAE constraint.
	* testsuite/20_util/any/102894.cc: New test.
This commit is contained in:
Jonathan Wakely 2021-10-22 22:55:00 +01:00
parent 030875c197
commit 0c1f737a48
2 changed files with 29 additions and 4 deletions

View File

@ -428,16 +428,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Exchange the states of two @c any objects.
inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); }
/// Create an any holding a @c _Tp constructed from @c __args.
/// Create an `any` holding a `_Tp` constructed from `__args...`.
template <typename _Tp, typename... _Args>
any make_any(_Args&&... __args)
inline
enable_if_t<is_constructible_v<any, in_place_type_t<_Tp>, _Args...>, any>
make_any(_Args&&... __args)
{
return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
}
/// Create an any holding a @c _Tp constructed from @c __il and @c __args.
/// Create an `any` holding a `_Tp` constructed from `__il` and `__args...`.
template <typename _Tp, typename _Up, typename... _Args>
any make_any(initializer_list<_Up> __il, _Args&&... __args)
inline
enable_if_t<is_constructible_v<any, in_place_type_t<_Tp>,
initializer_list<_Up>&, _Args...>, any>
make_any(initializer_list<_Up> __il, _Args&&... __args)
{
return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
}

View File

@ -0,0 +1,20 @@
// { dg-do compile { target c++17 } }
#include <any>
template<typename T, typename = void>
struct can_make_any
: std::false_type
{ };
template<typename T>
struct can_make_any<T, std::void_t<decltype(std::make_any<T>())>>
: std::true_type
{ };
struct move_only
{
move_only() = default;
move_only(move_only&&) = default;
};
static_assert( ! can_make_any<move_only>::value ); // PR libstdc++/102894