[Patch] Forward triviality in variant

Jonathan Wakely jwakely@redhat.com
Tue Jun 27 15:43:00 GMT 2017


On 18/06/17 12:37 -0700, Tim Shen via libstdc++ wrote:
>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.

Fold expressions don't short-circuit ... I'm not sure if they would be
allowed to for QoI.

>>> @@ -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`.

OK for trunk, thanks.




More information about the Libstdc++ mailing list