[Patch] Forward triviality in variant

Tim Shen via libstdc++ libstdc++@gcc.gnu.org
Sun Jun 18 19:37:00 GMT 2017


Besides the changes on the comments, I also changed the definition of
_S_trivial_copy_assign and _S_trivial_move_assign to match what union
has. See [class.copy.assign]p9.

On Thu, Jun 1, 2017 at 8:13 AM, Jonathan Wakely wrote:
> On 30/05/17 02:16 -0700, Tim Shen via libstdc++ wrote:
>>
>> diff --git a/libstdc++-v3/include/std/variant
>> b/libstdc++-v3/include/std/variant
>> index b9824a5182c..f81b815af09 100644
>> --- a/libstdc++-v3/include/std/variant
>> +++ b/libstdc++-v3/include/std/variant
>> @@ -290,6 +290,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>           __ref_cast<_Tp>(__t));
>>     }
>>
>> +  template<typename... _Types>
>> +    struct _Traits
>> +    {
>> +      static constexpr bool is_default_constructible_v =
>> +          is_default_constructible_v<typename _Nth_type<0,
>> _Types...>::type>;
>> +      static constexpr bool is_copy_constructible_v =
>> +          __and_<is_copy_constructible<_Types>...>::value;
>> +      static constexpr bool is_move_constructible_v =
>> +          __and_<is_move_constructible<_Types>...>::value;
>> +      static constexpr bool is_copy_assignable_v =
>> +          is_copy_constructible_v && is_move_constructible_v
>> +          && __and_<is_copy_assignable<_Types>...>::value;
>> +      static constexpr bool is_move_assignable_v =
>> +          is_move_constructible_v
>> +          && __and_<is_move_assignable<_Types>...>::value;
>
>
> It seems strange to me that these ones end with _v but the following
> ones don't. Could we make them all have no _v suffix?

Done. They are internal traits only for readability, so I shortened
the names and make them libstdc++ style, e.g. _S_copy_ctor.

>
>> +      static constexpr bool is_dtor_trivial =
>> +          __and_<is_trivially_destructible<_Types>...>::value;
>> +      static constexpr bool is_copy_ctor_trivial =
>> +          __and_<is_trivially_copy_constructible<_Types>...>::value;
>> +      static constexpr bool is_move_ctor_trivial =
>> +          __and_<is_trivially_move_constructible<_Types>...>::value;
>> +      static constexpr bool is_copy_assign_trivial =
>> +          is_dtor_trivial
>> +          && is_copy_ctor_trivial
>> +          && __and_<is_trivially_copy_assignable<_Types>...>::value;
>> +      static constexpr bool is_move_assign_trivial =
>> +          is_dtor_trivial
>> +          && is_move_ctor_trivial
>> +          && __and_<is_trivially_move_assignable<_Types>...>::value;
>> +
>> +      static constexpr bool is_default_ctor_noexcept =
>> +          is_nothrow_default_constructible_v<
>> +              typename _Nth_type<0, _Types...>::type>;
>> +      static constexpr bool is_copy_ctor_noexcept =
>> +          is_copy_ctor_trivial;
>> +      static constexpr bool is_move_ctor_noexcept =
>> +          is_move_ctor_trivial
>> +          || __and_<is_nothrow_move_constructible<_Types>...>::value;
>> +      static constexpr bool is_copy_assign_noexcept =
>> +          is_copy_assign_trivial;
>> +      static constexpr bool is_move_assign_noexcept =
>> +          is_move_assign_trivial ||
>> +          (is_move_ctor_noexcept
>> +           && __and_<is_nothrow_move_assignable<_Types>...>::value);
>> +    };
>
>
> Does using __and_ for any of those traits reduce the limit on the
> number of alternatives in a variant? We switched to using fold
> expressions in some contexts to avoid very deep instantiations, but I
> don't know if these will hit the same problem, but it looks like it
> will.

Done, use fold expression instead. At one point we changed some fold
expressions to __and_, because __and_ has short circuiting; does fold
expressions have short circuits too? Now that I think about it, short
circuiting in a constant fold expression should be a QoI issue.

>> @@ -928,12 +1107,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>         static constexpr size_t __index_of =
>>           __detail::__variant::__index_of_v<_Tp, _Types...>;
>>
>> +      using _Traits = __detail::__variant::_Traits<_Types...>;
>> +
>>     public:
>> -      constexpr variant()
>> -      noexcept(is_nothrow_default_constructible_v<__to_type<0>>) =
>> default;
>> -      variant(const variant&) = default;
>> +      variant() noexcept(_Traits::is_default_ctor_noexcept) = default;
>
>
> Do we need the exception specifications here? Will the =default make
> the right thing happen anyway? (And if not, won't we get an error by
> trying to define the constructors as noexcept when the implicit
> definition would not be noexcept?)

Done. Removed unnecessary noexcept qualifiers.

It turns out I mistakenly thought using "variant() = default" means
`variant() noexcept(false) = default`.

-- 
Regards,
Tim Shen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: c.diff
Type: text/x-patch
Size: 24736 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20170618/1b8dd71a/attachment.bin>


More information about the Libstdc++ mailing list