Add `const` overloads to tuple swap, construction and assignment
Rational of the these `tuple` changes needed for `zip`
1. Constructor overloads that takes non-const lvalue reference, and const rvalue reference.
Short answer: make `zip_view::iterator` model `indirectly_readable`.
Long answer: `indirectly_readable` requires a `common_reference` between "lvalue reference to `value_type`" and `reference`, in `zip`'s case, this could be `tuple<Foo>&` (lvalue reference to `value_type`) and `tuple<Foo&>` (`reference`). We need be able to construct `tuple<Foo&>` from `tuple<Foo>&`. pre-C++23, the `tuple`'s converting copy constructors takes only `const tuple<UTyles...>&`. This won't work here because we cannot bind `const Foo&` to `Foo&`.
2. const member assignment operators
Short answer: make `zip_view::iterator` model `indirectly_writable`
Long answer: `indirectly_writable` requires the type `const decltype(*it)` to be assignable. The `const` there is to prevent cases such as sorting a transformed of range of prvalue `string`. It would have compiled without `const` because `std::string{} = std::string{}` is a valid expression. but `const std::string{} = std::string{}` is not. If the range is a range of references, adding `const` doesn't do anything. `using T = int&`, then `const T` is also `int&`. So this `const` in the concept is to ban range of prvalues. However, in `zip` case, although the `reference` is prvalue `tuple`, it is really just a proxy. If we have a `tuple` of references, we do want to model the concept because the underlying ranges are writable. So we need the const assignment operators if underlying types are const assignable (reference types are const assignable).
3. const swap
because of the const assignment operator added above, the default `std::swap`'s triple-move would lead to wrong result for `const tuple<Foo&>`
Now, here is the summary of the implementations.
1. for constructors that takes cvref variation of `tuple<UTypes...>`, there used to be two SFINAE helper `_EnableCopyFromOtherTuple`, `_EnableMoveFromOtherTuple`. And the implementations of these two helpers seem to slightly differ from the spec. But now, we need 4 variations. Instead of adding another two, this change refactored it to a single one `_EnableCtrFromUTypesTuple`, which directly maps to the spec without changing the C++11 behaviour. However, we need the helper `__copy_cvref_t` to get the type of `std::get<i>(cvref tuple<Utypes...>)` for different cvref, so I made `__copy_cvref_t` to be available in C++11.
2. for constructors that takes variations of `std::pair`, there used to be four helpers `_EnableExplicitCopyFromPair`, `_EnableImplicitCopyFromPair`, `_EnableImplicitMoveFromPair`, `_EnableExplicitMoveFromPair`. Instead of adding another four, this change refactored into two helper `_EnableCtrFromPair` and `_BothImplicitlyConvertible`. This also removes the need to use `_nat`
3. for const member assignment operator, since the requirement is very simple, I haven't refactored the old code but instead directly adding the new c++23 code.
4. for const swap, I pretty much copy pasted the non-const version to make these overloads look consistent
5. while doing these change, I found two of the old constructors wasn't marked `constexpr` for C++20 but they should. fixed them and added unit tests