On Thu, 11 Jan 2024 at 22:17, Jonathan Wakely wrote:
>
> I'd like to commit this to trunk for GCC 14. Please take a look.
>
> -- >8 --
>
> This is the last part of PR libstdc++/108822 implementing P2255R2, which
> makes it ill-formed to create a std::tuple that would bind a reference
> to a temporary.
>
> The dangling checks are implemented as deleted constructors for C++20
> and higher, and as Debug Mode static assertions in the constructor body
> for older standards. This is similar to the r13-6084-g916ce577ad109b
> changes for std::pair.
>
> As part of this change, I've reimplemented most of std::tuple for C++20,
> making use of concepts to replace the enable_if constraints, and using
> conditional explicit to avoid duplicating most constructors. We could
> use conditional explicit for the C++11 implementation too (with pragmas
> to disables the -Wc++17-extensions warnings), but that should be done as
> a stage 1 change for GCC 15 rather than now.
>
> The partial specialization for std::tuple<T1, T2> is no longer used for
> C++20 (or more precisely, for a C++20 compiler that supports concepts
> and conditional explicit). The additional constructors and assignment
> operators that take std::pair arguments have been added to the C++20
> implementation of the primary template, with sizeof...(_Elements)==2
> constraints. This avoids reimplementing all the other constructors in
> the std::tuple<T1, T2> partial specialization to use concepts. This way
> we avoid four implementations of every constructor and only have three!
> (The primary template has an implementation of each constructor for
> C++11 and another for C++20, and the tuple<T1,T2> specialization has an
> implementation of each for C++11, so that's three for each constructor.)
>
> In order to make the constraints more efficient on the C++20 version of
> the default constructor I've also added a variable template for the
> __is_implicitly_default_constructible trait, implemented using concepts.

[snip]

> +#if __cpp_concepts // >= C++20
> +    private:
> +      template<typename... _UTypes>
> +       static consteval bool
> +       __assignable()

This causes errors for -std=c++17 -fconcepts-ts because that defines
__cpp_concepts=20157L, but does not allow C++20 consteval to be used.

I used a different condition for the constructors:
#if __cpp_concepts && __cpp_conditional_explicit // >= C++20
The difference is because the assignment ops don't use explicit. The
additional check for __cpp_conditional_explicit means it already
requires C++20, so doesn't match for -std=c++17 -fconcepts-ts. So that
preprocessor group didn't cause problems.
N.B. The different conditions means that for a compiler that supports
concepts but not conditional explicit we will use concepts for the
assignment ops, but not for the constructors. And you'll still get the
partial specialization for std::tuple<T1,T2>, and that partial
specialization will be missing the C++23 constructors for ranges::zip.
I think that's fine - if you don't have a good enough C++20 compiler
(i.e. one that defines __cpp_conditional_explicit) then you don't get
a complete C++20 std::tuple, let alone a complete C++23 std::tuple.
dealwithit.jpg

I could just use constexpr instead of consteval for those helper
functions, but I think I will add a check for __cpp_consteval. I don't
feel comfortable trying to make the new assignment ops work with
-std=c++17 -fconcepts-ts as there might be other interactions with
C++20 features that will go unnoticed, as we don't routinely test the
whole library with C++17 + Concepts TS.

Reply via email to