On Mon, 18 May 2026 at 16:48, Tomasz Kamiński <[email protected]> wrote:
>
> This implements additions from sections 4.3, 4.4, 4.5 of P3016R6.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/version.def (valarray): Define.
> * include/bits/version: Regenerate.
> * include/std/valarray (valarray::begin, valarray::end)
> (valarray::iterator, valarray::const_iterator)
> [__glibcxx_valarray >= 202511L]: Define.
> (std::begin(valarray<_Tp>&), std::begin(const valarray<_Tp>&))
> (std::end(valarray<_Tp>&), std::end(const valarray<_Tp>&)): Define
> only if __glibcxx_valarray < 202511L (i.e. not defined).
> * libstdc++-v3/include/bits/range_access.h (std::valarray)
> (std::begin(valarray<_Tp>&), std::begin(const valarray<_Tp>&))
> (std::end(valarray<_Tp>&), std::end(const valarray<_Tp>&)): Forward
> declare only if __glibcxx_valarray < 202511L (i.e. not defined).
> * testsuite/26_numerics/valarray/range_access3.cc: New test.
> ---
> I think it would make sense to backport this to C++11, or even C++98
> (see range_access3.cc test for example use). But doing C++26 for now.
>
> Tested on x86_64-linux. OK for trunk?
>
> libstdc++-v3/include/bits/range_access.h | 2 +
> libstdc++-v3/include/bits/version.def | 7 ++++
> libstdc++-v3/include/bits/version.h | 10 +++++
> libstdc++-v3/include/std/valarray | 34 ++++++++++++++-
> .../26_numerics/valarray/range_access3.cc | 41 +++++++++++++++++++
> 5 files changed, 92 insertions(+), 2 deletions(-)
> create mode 100644
> libstdc++-v3/testsuite/26_numerics/valarray/range_access3.cc
>
> diff --git a/libstdc++-v3/include/bits/range_access.h
> b/libstdc++-v3/include/bits/range_access.h
> index b89129f0233..01f79086852 100644
> --- a/libstdc++-v3/include/bits/range_access.h
> +++ b/libstdc++-v3/include/bits/range_access.h
> @@ -119,12 +119,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
> #if __cplusplus >= 201402L
>
> +#if __glibcxx_valarray < 202511L
> template<typename _Tp> class valarray;
> // These overloads must be declared for cbegin and cend to use them.
> template<typename _Tp> _Tp* begin(valarray<_Tp>&) noexcept;
> template<typename _Tp> const _Tp* begin(const valarray<_Tp>&) noexcept;
> template<typename _Tp> _Tp* end(valarray<_Tp>&) noexcept;
> template<typename _Tp> const _Tp* end(const valarray<_Tp>&) noexcept;
> +#endif
>
> /**
> * @brief Return an iterator pointing to the first element of
> diff --git a/libstdc++-v3/include/bits/version.def
> b/libstdc++-v3/include/bits/version.def
> index efcc0852af5..2f32a8bda98 100644
> --- a/libstdc++-v3/include/bits/version.def
> +++ b/libstdc++-v3/include/bits/version.def
> @@ -2418,6 +2418,13 @@ ftms = {
> };
> };
>
> +ftms = {
> + name = valarray;
> + values = {
> + v = 202511;
> + cxxmin = 26;
> + };
> +};
>
> // Standard test specifications.
> stds[97] = ">= 199711L";
> diff --git a/libstdc++-v3/include/bits/version.h
> b/libstdc++-v3/include/bits/version.h
> index 9402f25df37..517b9020ec6 100644
> --- a/libstdc++-v3/include/bits/version.h
> +++ b/libstdc++-v3/include/bits/version.h
> @@ -2685,4 +2685,14 @@
> #endif /* !defined(__cpp_lib_initializer_list) */
> #undef __glibcxx_want_initializer_list
>
> +#if !defined(__cpp_lib_valarray)
> +# if (__cplusplus > 202302L)
> +# define __glibcxx_valarray 202511L
> +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_valarray)
> +# define __cpp_lib_valarray 202511L
> +# endif
> +# endif
> +#endif /* !defined(__cpp_lib_valarray) */
> +#undef __glibcxx_want_valarray
> +
> #undef __glibcxx_want_all
> diff --git a/libstdc++-v3/include/std/valarray
> b/libstdc++-v3/include/std/valarray
> index abb158d22c3..ee11199f15f 100644
> --- a/libstdc++-v3/include/std/valarray
> +++ b/libstdc++-v3/include/std/valarray
> @@ -139,6 +139,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> };
> public:
> typedef _Tp value_type;
> +#if __glibcxx_valarray >= 202511L
> + typedef _Tp* iterator;
> + typedef const _Tp* const_iterator;
> +#endif
>
> // _lib.valarray.cons_ construct/destroy:
> /// Construct an empty array.
> @@ -572,6 +576,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> */
> void resize(size_t __size, _Tp __c = _Tp());
>
> +#if __glibcxx_valarray >= 202511L
> + /**
> + * @brief Return an iterator pointing to the first element of
> + * the valarray.
> + */
> + _GLIBCXX_NODISCARD iterator
> + begin() _GLIBCXX_NOTHROW
Is the use of the NODISCARD and NOTHROW macros to allow this to be
backported to C++98 later, if we choose to?
Because otherwise it could just be [[nodiscard]] and noexcept here.
The NOTHROW macro expands to throw() for C++98. If you only want
'noexcept' in C++11 and later, and nothing in C++98, that's just
_GLIBCXX_NOEXCEPT.
<valarray> has a mix of both today :-\
> + { return _M_data; }
> +
> + _GLIBCXX_NODISCARD const_iterator
> + begin() const _GLIBCXX_NOTHROW
> + { return _M_data; }
> +
> + /**
> + * @brief Return an iterator pointing to one past the last element
> of
> + * the valarray.
> + */
> + _GLIBCXX_NODISCARD iterator
> + end() _GLIBCXX_NOTHROW
> + { return _M_data + _M_size; }
> +
> + _GLIBCXX_NODISCARD const_iterator
> + end() const _GLIBCXX_NOTHROW
> + { return _M_data + _M_size; }
> +#endif
> +
> private:
> size_t _M_size;
> _Tp* __restrict__ _M_data;
> @@ -1218,7 +1248,7 @@ _DEFINE_BINARY_OPERATOR(>=, __greater_equal)
> #undef _DEFINE_BINARY_OPERATOR
> /// @endcond
>
> -#if __cplusplus >= 201103L
> +#if (__cplusplus >= 201103L) && (__glibcxx_valarray < 202511L)
> /**
> * @brief Return an iterator pointing to the first element of
> * the valarray.
> @@ -1272,7 +1302,7 @@ _DEFINE_BINARY_OPERATOR(>=, __greater_equal)
> else
> return nullptr;
> }
> -#endif // C++11
> +#endif // C++11 to C++23
>
> /// @} group numeric_arrays
>
> diff --git a/libstdc++-v3/testsuite/26_numerics/valarray/range_access3.cc
> b/libstdc++-v3/testsuite/26_numerics/valarray/range_access3.cc
> new file mode 100644
> index 00000000000..0027622124f
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/26_numerics/valarray/range_access3.cc
> @@ -0,0 +1,41 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <valarray>
> +#include <testsuite_hooks.h>
> +
> +void
> +test01()
> +{
> + std::valarray<double> va(3);
> + va[0] = 1.0; va[1] = 2.0; va[2] = 3.0;
> +
> + typename std::valarray<double>::iterator it = va.begin();
> + VERIFY( it != va.end() );
> + VERIFY( *it++ == 1.0 );
> + VERIFY( *it++ == 2.0 );
> + VERIFY( *it++ == 3.0 );
> + VERIFY( it == va.end() );
> +
> + const std::valarray<double>& cva = va;
> + typename std::valarray<double>::const_iterator cit = cva.begin();
> + VERIFY( cit != va.end() );
> + VERIFY( *cit++ == 1.0 );
> + VERIFY( *cit++ == 2.0 );
> + VERIFY( *cit++ == 3.0 );
> + VERIFY( cit == cva.end() );
> +}
> +
> +void
> +test02()
> +{
> + std::valarray<double> va;
> + VERIFY( va.begin() == va.end() );
> + const std::valarray<double>& cva = va;
> + VERIFY( cva.begin() == cva.end() );
> +}
> +
> +int main()
> +{
> + test01();
> + test02();
> +}
> --
> 2.54.0
>