Index: test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp =================================================================== --- test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp +++ test/std/utilities/variant/variant.variant/variant.assign/copy.pass.cpp @@ -385,6 +385,27 @@ #endif } +template +constexpr bool triviality_test = + std::is_trivially_copy_assignable>::value == + std::conjunction< + std::is_trivially_destructible..., + std::is_trivially_copy_constructible..., + std::is_trivially_copy_assignable...>::value; + +void test_triviality_extension() { +#if defined(_MSVC_STL_VER) + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); +#endif +} int main() { test_copy_assignment_empty_empty(); @@ -394,4 +415,5 @@ test_copy_assignment_different_index(); test_copy_assignment_sfinae(); test_copy_assignment_not_noexcept(); + test_triviality_extension(); } Index: test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp =================================================================== --- test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp +++ test/std/utilities/variant/variant.variant/variant.assign/move.pass.cpp @@ -308,6 +308,56 @@ #endif } +template +constexpr bool triviality_test = + // move assignment of variant is trivial when + std::is_trivially_move_assignable>::value == + std::conjunction< + // All Ts are trivially destructible and + std::is_trivially_destructible..., + // either + std::disjunction< + // All Ts are trivially move (constructible and assignable) so that + // variant's move assignment operator is non-deleted and trivial, or + std::conjunction< + std::is_trivially_move_constructible..., + std::is_trivially_move_assignable...>, + // At least one of the Ts is not move (constructible or assignable) so + // that variant's move assignment operator is *implicitly* deleted but + // all of the Ts are trivially *copy* (constructible and assignable) so + // that move assignment actually invokes the trivial copy assignment + // operator. + std::conjunction< + std::disjunction< + std::negation>..., + std::negation>...>, + std::is_trivially_copy_constructible..., + std::is_trivially_copy_assignable...>>>::value; + +void test_triviality_extension() { +#if defined(_MSVC_STL_VER) + struct TrivialCopyNontrivialMove { + TrivialCopyNontrivialMove(TrivialCopyNontrivialMove const&) = default; + TrivialCopyNontrivialMove(TrivialCopyNontrivialMove&&) noexcept {} + TrivialCopyNontrivialMove& operator=(TrivialCopyNontrivialMove const&) = default; + TrivialCopyNontrivialMove& operator=(TrivialCopyNontrivialMove&&) noexcept { + return *this; + } + }; + + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); +#endif +} + int main() { test_move_assignment_empty_empty(); test_move_assignment_non_empty_empty(); @@ -316,4 +366,5 @@ test_move_assignment_different_index(); test_move_assignment_sfinae(); test_move_assignment_noexcept(); + test_triviality_extension(); } Index: test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp =================================================================== --- test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp +++ test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -159,9 +159,27 @@ #endif } +template +constexpr bool triviality_test = + std::is_trivially_copy_constructible>::value == + std::conjunction...>::value; + +void test_triviality_extension() { +#if defined(_MSVC_STL_VER) + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); +#endif +} + int main() { test_copy_ctor_basic(); test_copy_ctor_valueless_by_exception(); test_copy_ctor_sfinae(); test_constexpr_copy_ctor_extension(); + test_triviality_extension(); } Index: test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp =================================================================== --- test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp +++ test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp @@ -197,10 +197,30 @@ #endif } +template +constexpr bool triviality_test = + std::is_trivially_move_constructible>::value == + std::conjunction...>::value; + +void test_triviality_extension() { +#if defined(_MSVC_STL_VER) + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); + static_assert(triviality_test, ""); +#endif +} + int main() { test_move_ctor_basic(); test_move_ctor_valueless_by_exception(); test_move_noexcept(); test_move_ctor_sfinae(); test_constexpr_move_ctor_extension(); + test_triviality_extension(); }