diff --git a/stl/inc/initializer_list b/stl/inc/initializer_list index b5d6ae7370e..9a6279a4a2f 100644 --- a/stl/inc/initializer_list +++ b/stl/inc/initializer_list @@ -51,20 +51,19 @@ public: return static_cast(_Last - _First); } + _NODISCARD constexpr bool empty() const noexcept { + return _First == _Last; + } + + _NODISCARD constexpr const _Elem* data() const noexcept { + return _First; + } + private: const _Elem* _First; const _Elem* _Last; }; -_EXPORT_STD template -_NODISCARD constexpr const _Elem* begin(initializer_list<_Elem> _Ilist) noexcept { - return _Ilist.begin(); -} - -_EXPORT_STD template -_NODISCARD constexpr const _Elem* end(initializer_list<_Elem> _Ilist) noexcept { - return _Ilist.end(); -} _STD_END // TRANSITION, non-_Ugly attribute tokens diff --git a/stl/inc/valarray b/stl/inc/valarray index a6a0909d9a8..73a6a0e8fa8 100644 --- a/stl/inc/valarray +++ b/stl/inc/valarray @@ -59,19 +59,9 @@ class valarray { // store array with various indexing options public: friend _Tidy_deallocate_guard; - template - friend _Ty2* begin(valarray<_Ty2>& _Array) noexcept /* strengthened */; - - template - friend const _Ty2* begin(const valarray<_Ty2>& _Array) noexcept /* strengthened */; - - template - friend _Ty2* end(valarray<_Ty2>& _Array) noexcept /* strengthened */; - - template - friend const _Ty2* end(const valarray<_Ty2>& _Array) noexcept /* strengthened */; - - using value_type = _Ty; + using value_type = _Ty; + using iterator = _Ty*; + using const_iterator = const _Ty*; valarray() = default; // construct empty valarray @@ -411,6 +401,22 @@ public: return _Mysize; } + _NODISCARD iterator begin() noexcept /* strengthened */ { + return _Myptr; + } + + _NODISCARD const_iterator begin() const noexcept /* strengthened */ { + return _Myptr; + } + + _NODISCARD iterator end() noexcept /* strengthened */ { + return _Myptr + _Mysize; + } + + _NODISCARD const_iterator end() const noexcept /* strengthened */ { + return _Myptr + _Mysize; + } + _NODISCARD const _Ty& operator[](size_t _Off) const noexcept /* strengthened */ { #if _MSVC_STL_HARDENING_VALARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off < _Mysize, "valarray subscript out of range"); @@ -612,26 +618,6 @@ void swap(valarray<_Ty>& _Left, valarray<_Ty>& _Right) noexcept { _Left.swap(_Right); } -_EXPORT_STD template -_NODISCARD _Ty* begin(valarray<_Ty>& _Array) noexcept /* strengthened */ { - return _Array._Myptr; -} - -_EXPORT_STD template -_NODISCARD const _Ty* begin(const valarray<_Ty>& _Array) noexcept /* strengthened */ { - return _Array._Myptr; -} - -_EXPORT_STD template -_NODISCARD _Ty* end(valarray<_Ty>& _Array) noexcept /* strengthened */ { - return _Array._Myptr + _Array.size(); -} - -_EXPORT_STD template -_NODISCARD const _Ty* end(const valarray<_Ty>& _Array) noexcept /* strengthened */ { - return _Array._Myptr + _Array.size(); -} - _EXPORT_STD template _NODISCARD valarray<_Ty> operator*(const valarray<_Ty>& _Left, const typename valarray<_Ty>::value_type& _Right) { const size_t _Size = _Left.size(); diff --git a/stl/inc/xutility b/stl/inc/xutility index 53a64c6c787..b88e899ea2b 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -2142,26 +2142,23 @@ constexpr bool disable_sized_sentinel_for, reverse_ite #endif // _HAS_CXX20 _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto begin(_Container& _Cont) noexcept(noexcept(_Cont.begin())) /* strengthened */ - -> decltype(_Cont.begin()) { +_NODISCARD _CONSTEXPR17 auto begin(_Container& _Cont) noexcept(noexcept(_Cont.begin())) -> decltype(_Cont.begin()) { return _Cont.begin(); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto begin(const _Container& _Cont) noexcept(noexcept(_Cont.begin())) /* strengthened */ +_NODISCARD _CONSTEXPR17 auto begin(const _Container& _Cont) noexcept(noexcept(_Cont.begin())) -> decltype(_Cont.begin()) { return _Cont.begin(); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto end(_Container& _Cont) noexcept(noexcept(_Cont.end())) /* strengthened */ - -> decltype(_Cont.end()) { +_NODISCARD _CONSTEXPR17 auto end(_Container& _Cont) noexcept(noexcept(_Cont.end())) -> decltype(_Cont.end()) { return _Cont.end(); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto end(const _Container& _Cont) noexcept(noexcept(_Cont.end())) /* strengthened */ - -> decltype(_Cont.end()) { +_NODISCARD _CONSTEXPR17 auto end(const _Container& _Cont) noexcept(noexcept(_Cont.end())) -> decltype(_Cont.end()) { return _Cont.end(); } @@ -2188,66 +2185,60 @@ _NODISCARD constexpr auto cend(const _Container& _Cont) noexcept(noexcept(_STD e } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto rbegin(_Container& _Cont) noexcept(noexcept(_Cont.rbegin())) /* strengthened */ - -> decltype(_Cont.rbegin()) { +_NODISCARD _CONSTEXPR17 auto rbegin(_Container& _Cont) noexcept(noexcept(_Cont.rbegin())) -> decltype(_Cont.rbegin()) { return _Cont.rbegin(); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto rbegin(const _Container& _Cont) noexcept(noexcept(_Cont.rbegin())) /* strengthened */ +_NODISCARD _CONSTEXPR17 auto rbegin(const _Container& _Cont) noexcept(noexcept(_Cont.rbegin())) -> decltype(_Cont.rbegin()) { return _Cont.rbegin(); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto rend(_Container& _Cont) noexcept(noexcept(_Cont.rend())) /* strengthened */ - -> decltype(_Cont.rend()) { +_NODISCARD _CONSTEXPR17 auto rend(_Container& _Cont) noexcept(noexcept(_Cont.rend())) -> decltype(_Cont.rend()) { return _Cont.rend(); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto rend(const _Container& _Cont) noexcept(noexcept(_Cont.rend())) /* strengthened */ - -> decltype(_Cont.rend()) { +_NODISCARD _CONSTEXPR17 auto rend(const _Container& _Cont) noexcept(noexcept(_Cont.rend())) -> decltype(_Cont.rend()) { return _Cont.rend(); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 reverse_iterator<_Ty*> rbegin(_Ty (&_Array)[_Size]) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR17 reverse_iterator<_Ty*> rbegin(_Ty (&_Array)[_Size]) noexcept { return reverse_iterator<_Ty*>(_Array + _Size); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 reverse_iterator<_Ty*> rend(_Ty (&_Array)[_Size]) noexcept /* strengthened */ { +_NODISCARD _CONSTEXPR17 reverse_iterator<_Ty*> rend(_Ty (&_Array)[_Size]) noexcept { return reverse_iterator<_Ty*>(_Array); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 reverse_iterator rbegin(initializer_list<_Elem> _Ilist) noexcept -/* strengthened */ { +_NODISCARD _CONSTEXPR17 reverse_iterator rbegin(initializer_list<_Elem> _Ilist) noexcept { return reverse_iterator(_Ilist.end()); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 reverse_iterator rend(initializer_list<_Elem> _Ilist) noexcept -/* strengthened */ { +_NODISCARD _CONSTEXPR17 reverse_iterator rend(initializer_list<_Elem> _Ilist) noexcept { return reverse_iterator(_Ilist.begin()); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto crbegin(const _Container& _Cont) noexcept(noexcept(_STD rbegin(_Cont))) /* strengthened */ +_NODISCARD _CONSTEXPR17 auto crbegin(const _Container& _Cont) noexcept(noexcept(_STD rbegin(_Cont))) -> decltype(_STD rbegin(_Cont)) { return _STD rbegin(_Cont); } _EXPORT_STD template -_NODISCARD _CONSTEXPR17 auto crend(const _Container& _Cont) noexcept(noexcept(_STD rend(_Cont))) /* strengthened */ +_NODISCARD _CONSTEXPR17 auto crend(const _Container& _Cont) noexcept(noexcept(_STD rend(_Cont))) -> decltype(_STD rend(_Cont)) { return _STD rend(_Cont); } _EXPORT_STD template -_NODISCARD constexpr auto size(const _Container& _Cont) noexcept(noexcept(_Cont.size())) /* strengthened */ - -> decltype(_Cont.size()) { +_NODISCARD constexpr auto size(const _Container& _Cont) noexcept(noexcept(_Cont.size())) -> decltype(_Cont.size()) { return _Cont.size(); } @@ -2258,8 +2249,7 @@ _NODISCARD constexpr size_t size(const _Ty (&)[_Size]) noexcept { #if _HAS_CXX20 _EXPORT_STD template -_NODISCARD constexpr auto ssize(const _Container& _Cont) noexcept(noexcept( - static_cast>>(_Cont.size()))) /* strengthened */ +_NODISCARD constexpr auto ssize(const _Container& _Cont) noexcept(noexcept(_Cont.size())) -> common_type_t> { using _Common = common_type_t>; return static_cast<_Common>(_Cont.size()); @@ -2272,8 +2262,7 @@ _NODISCARD constexpr ptrdiff_t ssize(const _Ty (&)[_Size]) noexcept { #endif // _HAS_CXX20 _EXPORT_STD template -_NODISCARD_EMPTY_NON_MEMBER constexpr auto empty(const _Container& _Cont) - noexcept(noexcept(_Cont.empty())) /* strengthened */ +_NODISCARD_EMPTY_NON_MEMBER constexpr auto empty(const _Container& _Cont) noexcept(noexcept(_Cont.empty())) -> decltype(_Cont.empty()) { return _Cont.empty(); } @@ -2283,20 +2272,13 @@ _NODISCARD_EMPTY_NON_MEMBER constexpr bool empty(const _Ty (&)[_Size]) noexcept return false; } -_EXPORT_STD template -_NODISCARD_EMPTY_NON_MEMBER constexpr bool empty(initializer_list<_Elem> _Ilist) noexcept { - return _Ilist.size() == 0; -} - _EXPORT_STD template -_NODISCARD constexpr auto data(_Container& _Cont) noexcept(noexcept(_Cont.data())) /* strengthened */ - -> decltype(_Cont.data()) { +_NODISCARD constexpr auto data(_Container& _Cont) noexcept(noexcept(_Cont.data())) -> decltype(_Cont.data()) { return _Cont.data(); } _EXPORT_STD template -_NODISCARD constexpr auto data(const _Container& _Cont) noexcept(noexcept(_Cont.data())) /* strengthened */ - -> decltype(_Cont.data()) { +_NODISCARD constexpr auto data(const _Container& _Cont) noexcept(noexcept(_Cont.data())) -> decltype(_Cont.data()) { return _Cont.data(); } @@ -2305,11 +2287,6 @@ _NODISCARD constexpr _Ty* data(_Ty (&_Array)[_Size]) noexcept { return _Array; } -_EXPORT_STD template -_NODISCARD constexpr const _Elem* data(initializer_list<_Elem> _Ilist) noexcept { - return _Ilist.begin(); -} - #if _HAS_CXX20 #if _HAS_CXX23 _EXPORT_STD template diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ea67cde8d2a..c28df8db1c6 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -80,6 +80,7 @@ // (__cpp_lib_freestanding_algorithm and __cpp_lib_freestanding_array only) // P2937R0 Freestanding Library: Remove strtok // P2968R2 Make std::ignore A First-Class Object +// P3016R6 Resolve Inconsistencies In begin/end For valarray And Braced Initializer Lists // P3223R2 Making istream::ignore() Less Surprising // P3323R1 Forbid atomic, Specify atomic_ref // (for atomic) @@ -1578,6 +1579,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_freestanding_tuple 202306L #define __cpp_lib_freestanding_utility 202306L #define __cpp_lib_generic_associative_lookup 201304L +#define __cpp_lib_initializer_list 202511L #define __cpp_lib_integer_sequence 201304L #define __cpp_lib_integral_constant_callable 201304L #define __cpp_lib_is_final 201402L @@ -1595,6 +1597,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #define __cpp_lib_transformation_trait_aliases 201304L #define __cpp_lib_tuple_element_t 201402L #define __cpp_lib_tuples_by_type 201304L +#define __cpp_lib_valarray 202511L // C++17 #define __cpp_lib_addressof_constexpr 201603L diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 171c3869c57..2eb83e0cf0a 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -136,6 +136,9 @@ std/language.support/support.limits/support.limits.general/mdspan.version.compil # libc++ has not implemented P2937R0: "Freestanding Library: Remove strtok" std/language.support/support.limits/support.limits.general/cstring.version.compile.pass.cpp FAIL +# libc++ has not implemented P3016R6: "Resolve Inconsistencies In begin/end For valarray And Braced Initializer Lists" +std/language.support/support.initlist/support.initlist.range/begin_end.pass.cpp FAIL + # libc++ has not implemented P3323R1: "Forbid atomic, Specify atomic_ref" std/atomics/atomics.ref/member_types.compile.pass.cpp FAIL diff --git a/tests/std/test.lst b/tests/std/test.lst index c44a4197217..934f31f1d5e 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -725,6 +725,7 @@ tests\P2693R1_text_formatting_header_stacktrace tests\P2693R1_text_formatting_header_thread tests\P2693R1_text_formatting_stacktrace tests\P2693R1_text_formatting_thread_id +tests\P3016R6_inconsistent_begin_end tests\P3107R5_enabled_specializations tests\P3349R1_contiguous_iterators_to_pointers tests\P3503R3_packaged_task_promise_with_allocator diff --git a/tests/std/tests/Dev11_1074023_constexpr/test.cpp b/tests/std/tests/Dev11_1074023_constexpr/test.cpp index d9b87f87247..47092a0a47e 100644 --- a/tests/std/tests/Dev11_1074023_constexpr/test.cpp +++ b/tests/std/tests/Dev11_1074023_constexpr/test.cpp @@ -53,7 +53,9 @@ constexpr auto int64_max = numeric_limits::max(); constexpr initializer_list il; STATIC_ASSERT(il.size() == 0); STATIC_ASSERT(il.begin() == il.end()); +#if _HAS_CXX17 STATIC_ASSERT(begin(il) == end(il)); +#endif // _HAS_CXX17 // TRANSITION, // constexpr error_category() noexcept; diff --git a/tests/std/tests/P3016R6_inconsistent_begin_end/env.lst b/tests/std/tests/P3016R6_inconsistent_begin_end/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/P3016R6_inconsistent_begin_end/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/P3016R6_inconsistent_begin_end/test.cpp b/tests/std/tests/P3016R6_inconsistent_begin_end/test.cpp new file mode 100644 index 00000000000..2b666b769b0 --- /dev/null +++ b/tests/std/tests/P3016R6_inconsistent_begin_end/test.cpp @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +namespace my { + template + void begin(std::initializer_list); + + template + void end(std::initializer_list); + + template + void empty(std::initializer_list); + + template + void data(std::initializer_list); +} // namespace my + +_CONSTEXPR17 bool test_initializer_list() { + // Check that free functions in std still can be invoked on std::initializer_list + std::initializer_list il = {1, 2, 3}; + + using namespace std; + (void) begin(il); + (void) cbegin(il); + (void) end(il); + (void) cend(il); + (void) size(il); + (void) empty(il); + (void) data(il); + + return true; +} + +// test_valarray() is not constexpr because valarray is not a literal type +bool test_valarray() { + // Check that free functions in std can be invoked on std::valarray + std::valarray v{1}; + + using namespace std; + (void) begin(v); + (void) cbegin(v); // Did not compile before P3016R6 + (void) end(v); + (void) cend(v); // Did not compile before P3016R6 + (void) size(v); + // There are no members 'empty' and 'data' of valarray + + return true; +} + +constexpr bool test_braced_init_list_iteration() { + int sum = 0; + for (int n : {1, 2, 3, 4}) { + sum += n; + } + return sum == 10; +} + +int main() { + // Check that free functions in std can't be invoked with braced-initializer-list. + // If they could be invoked, the following expressions would be ambiguous between std:: and my:: + using namespace std; + using namespace my; + STATIC_ASSERT(std::is_same_v); + STATIC_ASSERT(std::is_same_v); + STATIC_ASSERT(std::is_same_v); + STATIC_ASSERT(std::is_same_v); + + test_initializer_list(); + test_valarray(); + test_braced_init_list_iteration(); + +#if _HAS_CXX17 + STATIC_ASSERT(test_initializer_list()); +#endif // _HAS_CXX17 + STATIC_ASSERT(test_braced_init_list_iteration()); +} diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 3fe53dca792..aaf81e98164 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -491,6 +491,8 @@ STATIC_ASSERT(__cpp_lib_hypot == 201603L); STATIC_ASSERT(__cpp_lib_incomplete_container_elements == 201505L); +STATIC_ASSERT(__cpp_lib_initializer_list == 202511L); + #if _HAS_CXX20 STATIC_ASSERT(__cpp_lib_int_pow2 == 202002L); #elif defined(__cpp_lib_int_pow2) @@ -1037,6 +1039,8 @@ STATIC_ASSERT(__cpp_lib_unwrap_ref == 201811L); #error __cpp_lib_unwrap_ref is defined #endif +STATIC_ASSERT(__cpp_lib_valarray == 202511L); + #if _HAS_CXX20 STATIC_ASSERT(__cpp_lib_variant == 202106L); #elif _HAS_CXX17