libstdc++: Implement P1972R2 changes to std::variant (PR 95832)
G++ implements P1972R2 since r11-1597-0ca22d027ecc and so we no longer need the P0608R3 special case to prevent narrowing conversions to bool. Since non-GNU compilers don't necessarily implment P1972R2 yet, this may cause a regression for those compilers. There is no feature-test macro we can use to detect it though, so we'll have to live with it. libstdc++-v3/ChangeLog: PR libstdc++/95832 * include/std/variant (__detail::__variant::_Build_FUN): Remove partial specialization to prevent narrowing conversions to bool. * testsuite/20_util/variant/compile.cc: Test non-narrowing conversions to bool. * testsuite/20_util/variant/run.cc: Likewise.
This commit is contained in:
parent
a2c5150e40
commit
c98fc4eb3a
3 changed files with 44 additions and 16 deletions
|
@ -164,7 +164,7 @@ namespace __detail
|
|||
{
|
||||
namespace __variant
|
||||
{
|
||||
// Returns the first appearence of _Tp in _Types.
|
||||
// Returns the first appearance of _Tp in _Types.
|
||||
// Returns sizeof...(_Types) if _Tp is not in _Types.
|
||||
template<typename _Tp, typename... _Types>
|
||||
struct __index_of : std::integral_constant<size_t, 0> {};
|
||||
|
@ -733,10 +733,8 @@ namespace __variant
|
|||
// Helper used to check for valid conversions that don't involve narrowing.
|
||||
template<typename _Ti> struct _Arr { _Ti _M_x[1]; };
|
||||
|
||||
// Build an imaginary function FUN(Ti) for each alternative type Ti
|
||||
template<size_t _Ind, typename _Tp, typename _Ti,
|
||||
bool _Ti_is_cv_bool = is_same_v<remove_cv_t<_Ti>, bool>,
|
||||
typename = void>
|
||||
// "Build an imaginary function FUN(Ti) for each alternative type Ti"
|
||||
template<size_t _Ind, typename _Tp, typename _Ti, typename = void>
|
||||
struct _Build_FUN
|
||||
{
|
||||
// This function means 'using _Build_FUN<I, T, Ti>::_S_fun;' is valid,
|
||||
|
@ -744,24 +742,15 @@ namespace __variant
|
|||
void _S_fun();
|
||||
};
|
||||
|
||||
// ... for which Ti x[] = {std::forward<T>(t)}; is well-formed,
|
||||
// "... for which Ti x[] = {std::forward<T>(t)}; is well-formed."
|
||||
template<size_t _Ind, typename _Tp, typename _Ti>
|
||||
struct _Build_FUN<_Ind, _Tp, _Ti, false,
|
||||
struct _Build_FUN<_Ind, _Tp, _Ti,
|
||||
void_t<decltype(_Arr<_Ti>{{std::declval<_Tp>()}})>>
|
||||
{
|
||||
// This is the FUN function for type _Ti, with index _Ind
|
||||
static integral_constant<size_t, _Ind> _S_fun(_Ti);
|
||||
};
|
||||
|
||||
// ... and if Ti is cv bool, remove_cvref_t<T> is bool.
|
||||
template<size_t _Ind, typename _Tp, typename _Ti>
|
||||
struct _Build_FUN<_Ind, _Tp, _Ti, true,
|
||||
enable_if_t<is_same_v<__remove_cvref_t<_Tp>, bool>>>
|
||||
{
|
||||
// This is the FUN function for when _Ti is cv bool, with index _Ind
|
||||
static integral_constant<size_t, _Ind> _S_fun(_Ti);
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Variant,
|
||||
typename = make_index_sequence<variant_size_v<_Variant>>>
|
||||
struct _Build_FUNs;
|
||||
|
|
|
@ -155,6 +155,14 @@ void arbitrary_ctor()
|
|||
static_assert(!is_constructible_v<variant<int>, unsigned>);
|
||||
static_assert(!is_constructible_v<variant<bool>, int>);
|
||||
static_assert(!is_constructible_v<variant<bool>, void*>);
|
||||
|
||||
// P1957R2 Converting from T* to bool should be considered narrowing
|
||||
struct ConvertibleToBool
|
||||
{
|
||||
operator bool() const { return true; }
|
||||
};
|
||||
static_assert(is_constructible_v<variant<bool>, ConvertibleToBool>);
|
||||
static_assert(is_constructible_v<variant<bool, int>, ConvertibleToBool>);
|
||||
}
|
||||
|
||||
struct none { none() = delete; };
|
||||
|
|
|
@ -139,6 +139,20 @@ void arbitrary_ctor()
|
|||
variant<float, big_int> v3 = 0;
|
||||
VERIFY(v3.index() == 1);
|
||||
}
|
||||
|
||||
{
|
||||
// P1957R2 Converting from T* to bool should be considered narrowing
|
||||
struct ConvertibleToBool
|
||||
{
|
||||
operator bool() const { return true; }
|
||||
};
|
||||
variant<bool> v1 = ConvertibleToBool();
|
||||
VERIFY(std::get<0>(v1) == true);
|
||||
variant<bool, int> v2 = ConvertibleToBool();
|
||||
VERIFY(std::get<0>(v2) == true);
|
||||
variant<int, bool> v3 = ConvertibleToBool();
|
||||
VERIFY(std::get<1>(v3) == true);
|
||||
}
|
||||
}
|
||||
|
||||
struct ThrowingMoveCtorThrowsCopyCtor
|
||||
|
@ -226,6 +240,23 @@ void arbitrary_assign()
|
|||
v3 = 0;
|
||||
VERIFY(v3.index() == 1);
|
||||
}
|
||||
|
||||
{
|
||||
// P1957R2 Converting from T* to bool should be considered narrowing
|
||||
struct ConvertibleToBool
|
||||
{
|
||||
operator bool() const { return true; }
|
||||
};
|
||||
variant<bool> v1;
|
||||
v1 = ConvertibleToBool();
|
||||
VERIFY(std::get<0>(v1) == true);
|
||||
variant<bool, int> v2;
|
||||
v2 = ConvertibleToBool();
|
||||
VERIFY(std::get<0>(v2) == true);
|
||||
variant<int, bool> v3;
|
||||
v3 = ConvertibleToBool();
|
||||
VERIFY(std::get<1>(v3) == true);
|
||||
}
|
||||
}
|
||||
|
||||
void dtor()
|
||||
|
|
Loading…
Add table
Reference in a new issue