Skip to content

Commit ab60075

Browse files
C++20 Standard Library Modules! (#3977)
After discussion and buy-in from other Standard Library maintainers, we've decided to support the named modules (`std` and `std.compat`) from C++23 in C++20 mode.
1 parent bbb6739 commit ab60075

File tree

8 files changed

+61
-17
lines changed

8 files changed

+61
-17
lines changed

stl/inc/ctime

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ _EXPORT_STD using _CSTD strftime;
2929
_EXPORT_STD using _CSTD timespec;
3030
#endif // _HAS_CXX17
3131

32-
#if _HAS_CXX23 && defined(_BUILD_STD_MODULE) // TRANSITION, OS-33790456
32+
#ifdef _BUILD_STD_MODULE // TRANSITION, OS-33790456
3333
_STL_DISABLE_DEPRECATED_WARNING
3434

3535
_EXPORT_STD

stl/inc/yvals_core.h

+15-13
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@
292292
// P2418R2 Add Support For std::generator-like Types To std::format
293293
// P2419R2 Clarify Handling Of Encodings In Localized Formatting Of chrono Types
294294
// P2432R1 Fix istream_view
295+
// P2465R3 Standard Library Modules std And std.compat
295296
// P2508R1 basic_format_string, format_string, wformat_string
296297
// P2520R0 move_iterator<T*> Should Be A Random-Access Iterator
297298
// P2538R1 ADL-Proof projected
@@ -365,7 +366,6 @@
365366
// P2443R1 views::chunk_by
366367
// P2445R1 forward_like()
367368
// P2446R2 views::as_rvalue
368-
// P2465R3 Standard Library Modules std And std.compat
369369
// P2467R1 ios_base::noreplace: Exclusive Mode For fstreams
370370
// P2474R2 views::repeat
371371
// P2494R2 Relaxing Range Adaptors To Allow Move-Only Types
@@ -928,11 +928,14 @@ _EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC 19.36 or ne
928928
#endif // ^^^ inline (not constexpr) in C++20 and earlier ^^^
929929

930930
// P2465R3 Standard Library Modules std And std.compat
931-
#if _HAS_CXX23 && defined(_BUILD_STD_MODULE)
931+
#ifdef _BUILD_STD_MODULE
932+
#if !_HAS_CXX20
933+
#error The Standard Library Modules are available only with C++20 or later.
934+
#endif // ^^^ !_HAS_CXX20 ^^^
932935
#define _EXPORT_STD export
933-
#else // _HAS_CXX23 && defined(_BUILD_STD_MODULE)
936+
#else // ^^^ defined(_BUILD_STD_MODULE) / !defined(_BUILD_STD_MODULE) vvv
934937
#define _EXPORT_STD
935-
#endif // _HAS_CXX23 && defined(_BUILD_STD_MODULE)
938+
#endif // ^^^ !defined(_BUILD_STD_MODULE) ^^^
936939

937940
// P0607R0 Inline Variables For The STL
938941
#if _HAS_CXX17
@@ -1752,6 +1755,10 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
17521755
#define __cpp_lib_list_remove_return_type 201806L
17531756
#define __cpp_lib_math_constants 201907L
17541757

1758+
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, Clang and EDG support for modules
1759+
#define __cpp_lib_modules 202207L
1760+
#endif // !defined(__clang__) && !defined(__EDG__)
1761+
17551762
#ifdef __cpp_lib_concepts
17561763
#define __cpp_lib_move_iterator_concept 202207L
17571764
#endif // defined(__cpp_lib_concepts)
@@ -1793,15 +1800,10 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
17931800
#define __cpp_lib_formatters 202302L
17941801
#endif // defined(__cpp_lib_concepts)
17951802

1796-
#define __cpp_lib_forward_like 202207L
1797-
#define __cpp_lib_invoke_r 202106L
1798-
#define __cpp_lib_ios_noreplace 202207L
1799-
#define __cpp_lib_is_scoped_enum 202011L
1800-
1801-
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, Clang and EDG support for modules
1802-
#define __cpp_lib_modules 202207L
1803-
#endif // !defined(__clang__) && !defined(__EDG__)
1804-
1803+
#define __cpp_lib_forward_like 202207L
1804+
#define __cpp_lib_invoke_r 202106L
1805+
#define __cpp_lib_ios_noreplace 202207L
1806+
#define __cpp_lib_is_scoped_enum 202011L
18051807
#define __cpp_lib_move_only_function 202110L
18061808

18071809
#ifdef __cpp_lib_concepts

stl/modules/std.ixx

+10
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ export module std;
5757
#include <deque>
5858
#include <exception>
5959
#include <execution>
60+
#if _HAS_CXX23
6061
#include <expected>
62+
#endif // _HAS_CXX23
6163
#include <filesystem>
6264
#include <format>
6365
#include <forward_list>
@@ -84,7 +86,9 @@ export module std;
8486
#include <numeric>
8587
#include <optional>
8688
#include <ostream>
89+
#if _HAS_CXX23
8790
#include <print>
91+
#endif // _HAS_CXX23
8892
#include <queue>
8993
#include <random>
9094
#include <ranges>
@@ -96,12 +100,18 @@ export module std;
96100
#include <shared_mutex>
97101
#include <source_location>
98102
#include <span>
103+
#if _HAS_CXX23
99104
#include <spanstream>
105+
#endif // _HAS_CXX23
100106
#include <sstream>
101107
#include <stack>
108+
#if _HAS_CXX23
102109
#include <stacktrace>
110+
#endif // _HAS_CXX23
103111
#include <stdexcept>
112+
#if _HAS_CXX23
104113
#include <stdfloat>
114+
#endif // _HAS_CXX23
105115
#include <stop_token>
106116
#include <streambuf>
107117
#include <string>

tests/std/include/test_header_units_and_modules.hpp

+20
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,14 @@ void test_execution() {
216216
assert(count(execution::par, begin(arr), end(arr), 0) == 4);
217217
}
218218

219+
#if TEST_STANDARD >= 23
219220
void test_expected() {
220221
using namespace std;
221222
puts("Testing <expected>.");
222223
constexpr expected<double, int> test{unexpect, 42};
223224
assert(test.error() == 42);
224225
}
226+
#endif // TEST_STANDARD >= 23
225227

226228
void test_filesystem() {
227229
using namespace std;
@@ -492,6 +494,7 @@ void test_ostream() {
492494
assert(os.rdbuf() == nullptr);
493495
}
494496

497+
#if TEST_STANDARD >= 23
495498
void test_print() {
496499
using namespace std;
497500
puts("Testing <print>.");
@@ -501,6 +504,7 @@ void test_print() {
501504
println(cout, "The answer to life, the universe, and everything: {}", 42);
502505
#endif // _CPPRTTI
503506
}
507+
#endif // TEST_STANDARD >= 23
504508

505509
void test_queue() {
506510
using namespace std;
@@ -688,6 +692,7 @@ void test_span() {
688692
static_assert(mid[0] == 22 && mid[1] == 33 && mid[2] == 44);
689693
}
690694

695+
#if TEST_STANDARD >= 23
691696
void test_spanstream() {
692697
using namespace std;
693698
puts("Testing <spanstream>.");
@@ -720,6 +725,7 @@ void test_spanstream() {
720725
s << 10 << 20 << 30;
721726
assert(equal(begin(s.span()), end(s.span()), begin(expected_val), end(expected_val)));
722727
}
728+
#endif // TEST_STANDARD >= 23
723729

724730
void test_sstream() {
725731
using namespace std;
@@ -746,6 +752,7 @@ void test_stack() {
746752
assert(s.empty());
747753
}
748754

755+
#if TEST_STANDARD >= 23
749756
__declspec(dllexport) void test_stacktrace() { // export test_stacktrace to have it named even without debug info
750757
using namespace std;
751758
puts("Testing <stacktrace>.");
@@ -761,6 +768,7 @@ __declspec(dllexport) void test_stacktrace() { // export test_stacktrace to have
761768

762769
assert(desc == "test_stacktrace");
763770
}
771+
#endif // TEST_STANDARD >= 23
764772

765773
void test_stdexcept() {
766774
using namespace std;
@@ -778,11 +786,13 @@ void test_stdexcept() {
778786
assert(caught_puppies);
779787
}
780788

789+
#if TEST_STANDARD >= 23
781790
void test_stdfloat() {
782791
using namespace std;
783792
puts("Testing <stdfloat>.");
784793
// `namespace std` is available, so we're done.
785794
}
795+
#endif // TEST_STANDARD >= 23
786796

787797
void test_stop_token() {
788798
using namespace std;
@@ -1080,7 +1090,9 @@ void all_cpp_header_tests() {
10801090
test_deque();
10811091
test_exception();
10821092
test_execution();
1093+
#if TEST_STANDARD >= 23
10831094
test_expected();
1095+
#endif // TEST_STANDARD >= 23
10841096
test_filesystem();
10851097
test_format();
10861098
test_forward_list();
@@ -1107,7 +1119,9 @@ void all_cpp_header_tests() {
11071119
test_numeric();
11081120
test_optional();
11091121
test_ostream();
1122+
#if TEST_STANDARD >= 23
11101123
test_print();
1124+
#endif // TEST_STANDARD >= 23
11111125
test_queue();
11121126
test_random();
11131127
test_ranges();
@@ -1119,12 +1133,18 @@ void all_cpp_header_tests() {
11191133
test_shared_mutex();
11201134
test_source_location();
11211135
test_span();
1136+
#if TEST_STANDARD >= 23
11221137
test_spanstream();
1138+
#endif // TEST_STANDARD >= 23
11231139
test_sstream();
11241140
test_stack();
1141+
#if TEST_STANDARD >= 23
11251142
test_stacktrace();
1143+
#endif // TEST_STANDARD >= 23
11261144
test_stdexcept();
1145+
#if TEST_STANDARD >= 23
11271146
test_stdfloat();
1147+
#endif // TEST_STANDARD >= 23
11281148
test_stop_token();
11291149
test_streambuf();
11301150
test_string();

tests/std/tests/P1502R1_standard_library_header_units/env.lst

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ RUNALL_INCLUDE ..\..\..\universal_prefix.lst
55
RUNALL_CROSSLIST
66
PM_CL="/w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER"
77
RUNALL_CROSSLIST
8-
PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /std:c++latest"
8+
PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=20 /std:c++20"
9+
PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=23 /std:c++latest"
910
RUNALL_CROSSLIST
1011
PM_CL="/Zc:preprocessor"
1112
RUNALL_CROSSLIST

tests/std/tests/P1502R1_standard_library_header_units/test.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import <coroutine>;
2727
import <deque>;
2828
import <exception>;
2929
import <execution>;
30+
#if TEST_STANDARD >= 23
3031
import <expected>;
32+
#endif // TEST_STANDARD >= 23
3133
import <filesystem>;
3234
import <format>;
3335
import <forward_list>;
@@ -54,7 +56,9 @@ import <numbers>;
5456
import <numeric>;
5557
import <optional>;
5658
import <ostream>;
59+
#if TEST_STANDARD >= 23
5760
import <print>;
61+
#endif // TEST_STANDARD >= 23
5862
import <queue>;
5963
import <random>;
6064
import <ranges>;
@@ -66,12 +70,18 @@ import <set>;
6670
import <shared_mutex>;
6771
import <source_location>;
6872
import <span>;
73+
#if TEST_STANDARD >= 23
6974
import <spanstream>;
75+
#endif // TEST_STANDARD >= 23
7076
import <sstream>;
7177
import <stack>;
78+
#if TEST_STANDARD >= 23
7279
import <stacktrace>;
80+
#endif // TEST_STANDARD >= 23
7381
import <stdexcept>;
82+
#if TEST_STANDARD >= 23
7483
import <stdfloat>;
84+
#endif // TEST_STANDARD >= 23
7585
import <stop_token>;
7686
import <streambuf>;
7787
import <string>;

tests/std/tests/P2465R3_standard_library_modules/env.lst

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ RUNALL_INCLUDE ..\..\..\universal_prefix.lst
55
RUNALL_CROSSLIST
66
PM_CL="/w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER"
77
RUNALL_CROSSLIST
8-
PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /std:c++latest"
8+
PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=20 /std:c++20"
9+
PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=23 /std:c++latest"
910
RUNALL_CROSSLIST
1011
PM_CL="/Zc:preprocessor"
1112
RUNALL_CROSSLIST

tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,7 @@ STATIC_ASSERT(__cpp_lib_memory_resource == 201603L);
15061506
#endif
15071507
#endif
15081508

1509-
#if _HAS_CXX23 && !defined(__clang__) && !defined(__EDG__) // TRANSITION, Clang and EDG support for modules
1509+
#if _HAS_CXX20 && !defined(__clang__) && !defined(__EDG__) // TRANSITION, Clang and EDG support for modules
15101510
#ifndef __cpp_lib_modules
15111511
#error __cpp_lib_modules is not defined
15121512
#elif __cpp_lib_modules != 202207L

0 commit comments

Comments
 (0)