On Wed, 6 Mar 2019 at 11:33, Jonathan Wakely <[email protected]> wrote:
> >+ else if constexpr (is_rvalue_reference_v<_Tp&&>)
>
> I know what this is doing, but it still looks a little odd to ask if
> T&& is an rvalue-reference.
>
> Would it be clearer to structure this as:
>
> if constexpr (is_lvalue_reference_v<_Tp>)
> {
> if constexpr (is_const_v<remove_reference_t<_Tp>>)
> return static_cast<const variant<_Types...>&>(__rhs);
> else
> return static_cast<variant<_Types...>&>(__rhs);
> }
> else
> return static_cast<variant<_Types...>&&>(__rhs);
>
> ?
> >+ ::new (std::addressof(__this_mem))
>
> Is there any way that this can find the wrong operator new?
>
> Even if it can't, saying ::new ((void*)std::addressof(__this_mem))
> would avoid having to think about that question again in future.
>
> Therre are a few other new expressions where that applies too (several
> of them already there before your patch).
> >+ ::new (&__storage) remove_reference_t<decltype(__storage)>
>
> This one definitely needs to be cast to void* and needs to use
> addressof (or __addressof), otherwise ...
Sure thing; an incremental diff attached.
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 5138599..4d81ceb 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -145,12 +145,15 @@ namespace __variant
template <typename... _Types, typename _Tp>
decltype(auto) __variant_cast(_Tp&& __rhs)
{
- if constexpr (is_const_v<remove_reference_t<_Tp>>)
- return static_cast<const variant<_Types...>&>(__rhs);
- else if constexpr (is_rvalue_reference_v<_Tp&&>)
- return static_cast<variant<_Types...>&&>(__rhs);
+ if constexpr (is_lvalue_reference_v<_Tp>)
+ {
+ if constexpr (is_const_v<remove_reference_t<_Tp>>)
+ return static_cast<const variant<_Types...>&>(__rhs);
+ else
+ return static_cast<variant<_Types...>&>(__rhs);
+ }
else
- return static_cast<variant<_Types...>&>(__rhs);
+ return static_cast<variant<_Types...>&&>(__rhs);
}
namespace __detail
@@ -212,7 +215,8 @@ namespace __variant
{
template<typename... _Args>
constexpr _Uninitialized(in_place_index_t<0>, _Args&&... __args)
- { ::new (&_M_storage) _Type(std::forward<_Args>(__args)...); }
+ { ::new ((void*)std::addressof(_M_storage))
+ _Type(std::forward<_Args>(__args)...); }
const _Type& _M_get() const &
{ return *_M_storage._M_ptr(); }
@@ -427,7 +431,7 @@ namespace __variant
if constexpr (is_same_v<__remove_cvref_t<decltype(__rhs_mem)>,
remove_cv_t<_Type>>
&& !is_same_v<_Type, __variant_cookie>)
- ::new (std::addressof(__this_mem))
+ ::new ((void*)std::addressof(__this_mem))
_Type(std::forward<decltype(__rhs_mem)>(__rhs_mem));
return {};
}, __variant_cast<_Types...>(__lhs),
@@ -931,8 +935,9 @@ namespace __variant
{
__v._M_index = _Np;
auto&& __storage = __detail::__variant::__get<_Np>(__v);
- ::new (&__storage) remove_reference_t<decltype(__storage)>
- (std::forward<_Args>(__args)...);
+ ::new ((void*)std::addressof(__storage))
+ remove_reference_t<decltype(__storage)>
+ (std::forward<_Args>(__args)...);
}
template<typename _Tp, typename... _Types>