Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions stl/inc/execution
Original file line number Diff line number Diff line change
Expand Up @@ -73,36 +73,42 @@ 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
// guarantees, and requests termination on exceptions
//
// (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 {
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/LWG2510_tag_classes/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
207 changes: 207 additions & 0 deletions tests/std/tests/LWG2510_tag_classes/test.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cstddef>
#include <functional>
#include <list>
#include <memory>
#include <new>
#include <scoped_allocator>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#ifndef _M_CEE_PURE
#include <future>
#include <mutex>
#endif // _M_CEE_PURE

#if _HAS_CXX17
#include <execution>
#endif // _HAS_CXX17

#if _HAS_CXX20
#include <chrono>
#include <format>
#include <iterator>
#include <ranges>
#include <stop_token>
#endif // _HAS_CXX20

#if _HAS_CXX23
#include <expected>
#include <generator>
#include <mdspan>
#include <optional>
#endif // _HAS_CXX23

#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)

using namespace std;

// LWG-2510 "Tag types should not be DefaultConstructible"

template <class T>
void check_implicit_default_construction(const T&); // not defined

template <class T, class = void>
constexpr bool implicitly_default_constructible = false;
template <class T>
constexpr bool implicitly_default_constructible<T, void_t<decltype(check_implicit_default_construction<T>({}))>> = true;

STATIC_ASSERT(implicitly_default_constructible<int>);
STATIC_ASSERT(implicitly_default_constructible<void*>);

STATIC_ASSERT(!implicitly_default_constructible<void>);
STATIC_ASSERT(!implicitly_default_constructible<int&>);
STATIC_ASSERT(!implicitly_default_constructible<void()>);

template <class T>
void check_tag_class() { // COMPILE-ONLY
STATIC_ASSERT(is_default_constructible_v<T>);
STATIC_ASSERT(!implicitly_default_constructible<T>);

STATIC_ASSERT(is_copy_constructible_v<T>);
STATIC_ASSERT(is_move_constructible_v<T>);
STATIC_ASSERT(is_constructible_v<T, T&>);
STATIC_ASSERT(is_constructible_v<T, const T>);
STATIC_ASSERT(is_convertible_v<T&, T>);
STATIC_ASSERT(is_convertible_v<const T&, T>);
STATIC_ASSERT(is_convertible_v<T, T>);
STATIC_ASSERT(is_convertible_v<const T, T>);
STATIC_ASSERT(is_copy_assignable_v<T>);
STATIC_ASSERT(is_move_assignable_v<T>);
STATIC_ASSERT(is_assignable_v<T&, T&>);
STATIC_ASSERT(is_assignable_v<T&, const T>);

STATIC_ASSERT(is_nothrow_destructible_v<T>);

STATIC_ASSERT(!is_polymorphic_v<T>);

constexpr T constant_argument;
(void) constant_argument;

// desired properties not yet guaranteed by the Standard
STATIC_ASSERT(is_nothrow_default_constructible_v<T>);
STATIC_ASSERT(is_nothrow_copy_constructible_v<T>);
STATIC_ASSERT(is_nothrow_move_constructible_v<T>);
STATIC_ASSERT(is_nothrow_constructible_v<T, T&>);
STATIC_ASSERT(is_nothrow_constructible_v<T, const T>);
#if _HAS_CXX20
STATIC_ASSERT(is_nothrow_convertible_v<T&, T>);
STATIC_ASSERT(is_nothrow_convertible_v<const T&, T>);
STATIC_ASSERT(is_nothrow_convertible_v<T, T>);
STATIC_ASSERT(is_nothrow_convertible_v<const T, T>);
#endif // _HAS_CXX20
STATIC_ASSERT(is_nothrow_copy_assignable_v<T>);
STATIC_ASSERT(is_nothrow_move_assignable_v<T>);
STATIC_ASSERT(is_nothrow_assignable_v<T&, T&>);
STATIC_ASSERT(is_nothrow_assignable_v<T&, const T>);

STATIC_ASSERT(is_trivially_default_constructible_v<T>);
STATIC_ASSERT(is_trivially_copy_constructible_v<T>);
STATIC_ASSERT(is_trivially_move_constructible_v<T>);
STATIC_ASSERT(is_trivially_constructible_v<T, T&>);
STATIC_ASSERT(is_trivially_constructible_v<T, const T>);
STATIC_ASSERT(is_trivially_copy_assignable_v<T>);
STATIC_ASSERT(is_trivially_move_assignable_v<T>);
STATIC_ASSERT(is_trivially_assignable_v<T&, T&>);
STATIC_ASSERT(is_trivially_assignable_v<T&, const T>);
STATIC_ASSERT(is_trivially_destructible_v<T>);
STATIC_ASSERT(is_trivially_copyable_v<T>);

STATIC_ASSERT(is_standard_layout_v<T>);
STATIC_ASSERT(is_empty_v<T>); // 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<nothrow_t>();
check_tag_class<allocator_arg_t>();
check_tag_class<piecewise_construct_t>();
#ifndef _M_CEE_PURE
check_tag_class<adopt_lock_t>();
check_tag_class<defer_lock_t>();
check_tag_class<try_to_lock_t>();
#endif // _M_CEE_PURE

#if _HAS_CXX17
check_tag_class<in_place_t>();
check_tag_class<in_place_index_t<0>>();
check_tag_class<in_place_index_t<42>>();
check_tag_class<in_place_index_t<static_cast<size_t>(-1)>>();
check_tag_class<in_place_type_t<int>>();
check_tag_class<in_place_type_t<in_place_type_t<int>>>();
check_tag_class<in_place_type_t<void>>();
check_tag_class<in_place_type_t<void()>>();

// LWG-4273 "Standard execution policy types should be conventional tag class types"
check_tag_class<execution::sequenced_policy>();
check_tag_class<execution::parallel_policy>();
check_tag_class<execution::parallel_unsequenced_policy>();
#endif // _HAS_CXX17

#if _HAS_CXX20
check_tag_class<destroying_delete_t>();
check_tag_class<nostopstate_t>();
check_tag_class<chrono::last_spec>();

// LWG-4273 "Standard execution policy types should be conventional tag class types"
check_tag_class<execution::unsequenced_policy>();
#endif // _HAS_CXX20

#if _HAS_CXX23
check_tag_class<from_range_t>();
check_tag_class<unexpect_t>();
// 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<chrono::_Secret_time_zone_construct_tag>();
check_tag_class<chrono::_Secret_time_zone_link_construct_tag>();
check_tag_class<chrono::_Secret_tzdb_list_construct_tag>();
check_tag_class<ranges::_Construct_tag>();
#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
}
30 changes: 9 additions & 21 deletions tests/std/tests/VSO_0000000_more_pair_tuple_sfinae/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@

#include <cassert>
#include <memory>
#ifndef _M_CEE_PURE
#include <mutex>
#endif // _M_CEE_PURE
#include <new>
#include <string>
#include <tuple>
#include <type_traits>
Expand Down Expand Up @@ -42,39 +38,31 @@ STATIC_ASSERT(!is_constructible_v<tuple<NoDefault, NoDefault>, allocator_arg_t,


// LWG-2510 "Tag types should not be DefaultConstructible"
template <typename T, typename = void>
struct IsImplicitlyDefaultConstructible : false_type {};
template <class T, class = void>
constexpr bool implicitly_default_constructible = false;

template <typename T>
void ImplicitlyDefaultConstruct(const T&);
template <class T>
void check_implicit_default_construction(const T&); // not defined

template <typename T>
struct IsImplicitlyDefaultConstructible<T, void_t<decltype(ImplicitlyDefaultConstruct<T>({}))>> : true_type {};
template <class T>
constexpr bool implicitly_default_constructible<T, void_t<decltype(check_implicit_default_construction<T>({}))>> = true;

struct ExplicitDefault {
explicit ExplicitDefault() = default;
};

template <typename T>
constexpr bool OrdinaryDC = is_default_constructible_v<T> && IsImplicitlyDefaultConstructible<T>::value;
constexpr bool OrdinaryDC = is_default_constructible_v<T> && implicitly_default_constructible<T>;

template <typename T>
constexpr bool ExplicitDC = is_default_constructible_v<T> && !IsImplicitlyDefaultConstructible<T>::value;
constexpr bool ExplicitDC = is_default_constructible_v<T> && !implicitly_default_constructible<T>;

template <typename T>
constexpr bool VerbotenDC = !is_default_constructible_v<T> && !IsImplicitlyDefaultConstructible<T>::value;
constexpr bool VerbotenDC = !is_default_constructible_v<T> && !implicitly_default_constructible<T>;

STATIC_ASSERT(OrdinaryDC<int>);
STATIC_ASSERT(VerbotenDC<NoDefault>);
STATIC_ASSERT(ExplicitDC<ExplicitDefault>);
STATIC_ASSERT(ExplicitDC<nothrow_t>);
STATIC_ASSERT(ExplicitDC<piecewise_construct_t>);
STATIC_ASSERT(ExplicitDC<allocator_arg_t>);
#ifndef _M_CEE_PURE
STATIC_ASSERT(ExplicitDC<defer_lock_t>);
STATIC_ASSERT(ExplicitDC<try_to_lock_t>);
STATIC_ASSERT(ExplicitDC<adopt_lock_t>);
#endif // _M_CEE_PURE

using Expl = ExplicitDefault;
using NOPE = NoDefault;
Expand Down