diff --git a/stl/inc/execution b/stl/inc/execution index 5f5134f768f..3e890f8aed6 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -73,23 +73,27 @@ namespace execution { _EXPORT_STD class sequenced_policy { // indicates support for only sequential execution, and requests termination on exceptions public: + explicit sequenced_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = false; static constexpr bool _Ivdep = false; }; - _EXPORT_STD inline constexpr sequenced_policy seq{/* unspecified */}; + _EXPORT_STD inline constexpr sequenced_policy seq{}; _EXPORT_STD class parallel_policy { // indicates support by element access functions for parallel execution with parallel forward progress // guarantees, and requests termination on exceptions public: + explicit parallel_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = true; static constexpr bool _Ivdep = true; }; - _EXPORT_STD inline constexpr parallel_policy par{/* unspecified */}; + _EXPORT_STD inline constexpr parallel_policy par{}; _EXPORT_STD class parallel_unsequenced_policy { // indicates support by element access functions for parallel execution with weakly parallel forward progress @@ -97,12 +101,14 @@ namespace execution { // // (at this time, equivalent to parallel_policy) public: + explicit parallel_unsequenced_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = true; static constexpr bool _Ivdep = true; }; - _EXPORT_STD inline constexpr parallel_unsequenced_policy par_unseq{/* unspecified */}; + _EXPORT_STD inline constexpr parallel_unsequenced_policy par_unseq{}; #if _HAS_CXX20 _EXPORT_STD class unsequenced_policy { @@ -112,12 +118,14 @@ namespace execution { // (at this time, equivalent to sequenced_policy except for for_each(_n), destroy(_n), // uninitialized_default_construct(_n), and uninitialized_value_construct(_n)) public: + explicit unsequenced_policy() = default; // per LWG-4273 + using _Standard_execution_policy = int; static constexpr bool _Parallelize = false; static constexpr bool _Ivdep = true; }; - _EXPORT_STD inline constexpr unsequenced_policy unseq{/* unspecified */}; + _EXPORT_STD inline constexpr unsequenced_policy unseq{}; #endif // _HAS_CXX20 } // namespace execution diff --git a/tests/std/test.lst b/tests/std/test.lst index 666f255aae7..2ef39ff142a 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -268,6 +268,7 @@ tests\GH_005421_vector_algorithms_integer_class_type_iterator tests\GH_005472_do_not_overlap tests\GH_005553_regex_character_translation tests\LWG2381_num_get_floating_point +tests\LWG2510_tag_classes tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function tests\LWG3121_constrained_tuple_forwarding_ctor diff --git a/tests/std/tests/LWG2510_tag_classes/env.lst b/tests/std/tests/LWG2510_tag_classes/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/LWG2510_tag_classes/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/LWG2510_tag_classes/test.compile.pass.cpp b/tests/std/tests/LWG2510_tag_classes/test.compile.pass.cpp new file mode 100644 index 00000000000..5e7efbdf073 --- /dev/null +++ b/tests/std/tests/LWG2510_tag_classes/test.compile.pass.cpp @@ -0,0 +1,207 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _M_CEE_PURE +#include +#include +#endif // _M_CEE_PURE + +#if _HAS_CXX17 +#include +#endif // _HAS_CXX17 + +#if _HAS_CXX20 +#include +#include +#include +#include +#include +#endif // _HAS_CXX20 + +#if _HAS_CXX23 +#include +#include +#include +#include +#endif // _HAS_CXX23 + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +using namespace std; + +// LWG-2510 "Tag types should not be DefaultConstructible" + +template +void check_implicit_default_construction(const T&); // not defined + +template +constexpr bool implicitly_default_constructible = false; +template +constexpr bool implicitly_default_constructible({}))>> = true; + +STATIC_ASSERT(implicitly_default_constructible); +STATIC_ASSERT(implicitly_default_constructible); + +STATIC_ASSERT(!implicitly_default_constructible); +STATIC_ASSERT(!implicitly_default_constructible); +STATIC_ASSERT(!implicitly_default_constructible); + +template +void check_tag_class() { // COMPILE-ONLY + STATIC_ASSERT(is_default_constructible_v); + STATIC_ASSERT(!implicitly_default_constructible); + + STATIC_ASSERT(is_copy_constructible_v); + STATIC_ASSERT(is_move_constructible_v); + STATIC_ASSERT(is_constructible_v); + STATIC_ASSERT(is_constructible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_convertible_v); + STATIC_ASSERT(is_copy_assignable_v); + STATIC_ASSERT(is_move_assignable_v); + STATIC_ASSERT(is_assignable_v); + STATIC_ASSERT(is_assignable_v); + + STATIC_ASSERT(is_nothrow_destructible_v); + + STATIC_ASSERT(!is_polymorphic_v); + + constexpr T constant_argument; + (void) constant_argument; + + // desired properties not yet guaranteed by the Standard + STATIC_ASSERT(is_nothrow_default_constructible_v); + STATIC_ASSERT(is_nothrow_copy_constructible_v); + STATIC_ASSERT(is_nothrow_move_constructible_v); + STATIC_ASSERT(is_nothrow_constructible_v); + STATIC_ASSERT(is_nothrow_constructible_v); +#if _HAS_CXX20 + STATIC_ASSERT(is_nothrow_convertible_v); + STATIC_ASSERT(is_nothrow_convertible_v); + STATIC_ASSERT(is_nothrow_convertible_v); + STATIC_ASSERT(is_nothrow_convertible_v); +#endif // _HAS_CXX20 + STATIC_ASSERT(is_nothrow_copy_assignable_v); + STATIC_ASSERT(is_nothrow_move_assignable_v); + STATIC_ASSERT(is_nothrow_assignable_v); + STATIC_ASSERT(is_nothrow_assignable_v); + + STATIC_ASSERT(is_trivially_default_constructible_v); + STATIC_ASSERT(is_trivially_copy_constructible_v); + STATIC_ASSERT(is_trivially_move_constructible_v); + STATIC_ASSERT(is_trivially_constructible_v); + STATIC_ASSERT(is_trivially_constructible_v); + STATIC_ASSERT(is_trivially_copy_assignable_v); + STATIC_ASSERT(is_trivially_move_assignable_v); + STATIC_ASSERT(is_trivially_assignable_v); + STATIC_ASSERT(is_trivially_assignable_v); + STATIC_ASSERT(is_trivially_destructible_v); + STATIC_ASSERT(is_trivially_copyable_v); + + STATIC_ASSERT(is_standard_layout_v); + STATIC_ASSERT(is_empty_v); // only guaranteed for allocator_arg_t and piecewise_construct_t + + // ABI-specific, seemingly agreed among mainstream implementations + STATIC_ASSERT(sizeof(T) == 1); +} + +void check_standard_tags() { // COMPILE-ONLY + check_tag_class(); + check_tag_class(); + check_tag_class(); +#ifndef _M_CEE_PURE + check_tag_class(); + check_tag_class(); + check_tag_class(); +#endif // _M_CEE_PURE + +#if _HAS_CXX17 + check_tag_class(); + check_tag_class>(); + check_tag_class>(); + check_tag_class(-1)>>(); + check_tag_class>(); + check_tag_class>>(); + check_tag_class>(); + check_tag_class>(); + + // LWG-4273 "Standard execution policy types should be conventional tag class types" + check_tag_class(); + check_tag_class(); + check_tag_class(); +#endif // _HAS_CXX17 + +#if _HAS_CXX20 + check_tag_class(); + check_tag_class(); + check_tag_class(); + + // LWG-4273 "Standard execution policy types should be conventional tag class types" + check_tag_class(); +#endif // _HAS_CXX20 + +#if _HAS_CXX23 + check_tag_class(); + check_tag_class(); + // TODO: Cover sorted_equivalent_t and sorted_unique_t once flat_meow are implemented. +#endif // _HAS_CXX23 + + // TODO: Update to cover newly introduced tag class types. +} + +// We intentionally implement internal disambiguation tag types like standard ones. +void check_implementation_details() { // COMPILE-ONLY + // TODO: Synchronize the check list with actual implementation details. + check_tag_class<_Alloc_exact_args_t>(); + check_tag_class<_Alloc_unpack_tuple_t>(); + check_tag_class<_Exact_args_t>(); + check_tag_class<_Leave_proxy_unbound>(); + check_tag_class<_Move_allocator_tag>(); + check_tag_class<_One_then_variadic_args_t>(); + check_tag_class<_String_constructor_concat_tag>(); + check_tag_class<_Secret_copyability_ignoring_tag>(); + check_tag_class<_Secret_scoped_allocator_construct_tag>(); + check_tag_class<_Unforced>(); + check_tag_class<_Unpack_tuple_t>(); + check_tag_class<_Value_init_tag>(); + check_tag_class<_Zero_then_variadic_args_t>(); +#ifndef _M_CEE_PURE + check_tag_class<_From_raw_state_tag>(); +#endif // _M_CEE_PURE + +#if _HAS_CXX17 + check_tag_class<_No_init_tag>(); + check_tag_class<_Not_fn_tag>(); +#endif // _HAS_CXX17 + +#if _HAS_CXX20 + check_tag_class<_Auto_id_tag>(); + check_tag_class<_For_overwrite_tag>(); + check_tag_class<_Variantish_empty_tag>(); + check_tag_class(); + check_tag_class(); + check_tag_class(); + check_tag_class(); +#endif // _HAS_CXX20 + +#if _HAS_CXX23 + check_tag_class<_Construct_expected_from_invoke_result_tag>(); + check_tag_class<_Construct_from_invoke_result_tag>(); + check_tag_class<_Extents_from_tuple>(); + check_tag_class<_Gen_detail::_Secret_tag>(); +#endif // _HAS_CXX23 +} diff --git a/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp b/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp index fb07af86b09..21a3bf66076 100644 --- a/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp +++ b/tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp @@ -3,10 +3,6 @@ #include #include -#ifndef _M_CEE_PURE -#include -#endif // _M_CEE_PURE -#include #include #include #include @@ -42,39 +38,31 @@ STATIC_ASSERT(!is_constructible_v, allocator_arg_t, // LWG-2510 "Tag types should not be DefaultConstructible" -template -struct IsImplicitlyDefaultConstructible : false_type {}; +template +constexpr bool implicitly_default_constructible = false; -template -void ImplicitlyDefaultConstruct(const T&); +template +void check_implicit_default_construction(const T&); // not defined -template -struct IsImplicitlyDefaultConstructible({}))>> : true_type {}; +template +constexpr bool implicitly_default_constructible({}))>> = true; struct ExplicitDefault { explicit ExplicitDefault() = default; }; template -constexpr bool OrdinaryDC = is_default_constructible_v && IsImplicitlyDefaultConstructible::value; +constexpr bool OrdinaryDC = is_default_constructible_v && implicitly_default_constructible; template -constexpr bool ExplicitDC = is_default_constructible_v && !IsImplicitlyDefaultConstructible::value; +constexpr bool ExplicitDC = is_default_constructible_v && !implicitly_default_constructible; template -constexpr bool VerbotenDC = !is_default_constructible_v && !IsImplicitlyDefaultConstructible::value; +constexpr bool VerbotenDC = !is_default_constructible_v && !implicitly_default_constructible; STATIC_ASSERT(OrdinaryDC); STATIC_ASSERT(VerbotenDC); STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -#ifndef _M_CEE_PURE -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -STATIC_ASSERT(ExplicitDC); -#endif // _M_CEE_PURE using Expl = ExplicitDefault; using NOPE = NoDefault;