[RFC] Deprecate non-standard constructors in std::pair
Jonathan Wakely
jwakely@redhat.com
Wed Apr 7 18:17:13 GMT 2021
On 07/04/21 19:00 +0100, Jonathan Wakely wrote:
>On 07/04/21 17:59 +0100, Jonathan Wakely wrote:
>>On 07/04/21 13:46 +0100, Jonathan Wakely wrote:
>>>On 07/04/21 15:41 +0300, Ville Voutilainen via Libstdc++ wrote:
>>>>On Wed, 7 Apr 2021 at 15:31, Jonathan Wakely via Libstdc++
>>>><libstdc++@gcc.gnu.org> wrote:
>>>>>I propose that we deprecate the constructors for C++11/14/17/20 in
>>>>>stage 1, and do not support them at all in C++23 mode once P1951 is
>>>>>supported. I have a patch which I'll send in stage 1 (it also uses
>>>>>C++20 concepts to simplify std::pair and fix PR 97930).
>>>>>
>>>>>After a period of deprecation we could remove them, and support P1951
>>>>>for -std=gnu++11/14/17/20 too so that {} continues to work.
>>>>
>>>>The proposal sounds good to me.
>>>
>>>Thanks. I've created https://gcc.gnu.org/PR99957 so I don't forget.
>>
>>Here's a patch to implement it, for stage 1.
>
>
>>diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
>>index 70262f9508f..883d7441b3d 100644
>>--- a/libstdc++-v3/include/bits/stl_pair.h
>>+++ b/libstdc++-v3/include/bits/stl_pair.h
>>@@ -128,34 +128,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> is_convertible<_U2&&, _T2>>::value;
>> }
>>
>>- template <bool __implicit, typename _U1, typename _U2>
>>- static constexpr bool _CopyMovePair()
>>- {
>>- using __do_converts = __and_<is_convertible<const _U1&, _T1>,
>>- is_convertible<_U2&&, _T2>>;
>>- using __converts = typename conditional<__implicit,
>>- __do_converts,
>>- __not_<__do_converts>>::type;
>>- return __and_<is_constructible<_T1, const _U1&>,
>>- is_constructible<_T2, _U2&&>,
>>- __converts
>>- >::value;
>>- }
>>
>> template <bool __implicit, typename _U1, typename _U2>
>>- static constexpr bool _MoveCopyPair()
>>+ static constexpr bool _DeprConsPair()
>> {
>> using __do_converts = __and_<is_convertible<_U1&&, _T1>,
>>- is_convertible<const _U2&, _T2>>;
>>+ is_convertible<_U2&&, _T2>>;
>> using __converts = typename conditional<__implicit,
>>- __do_converts,
>>- __not_<__do_converts>>::type;
>>+ __do_converts,
>>+ __not_<__do_converts>>::type;
>> return __and_<is_constructible<_T1, _U1&&>,
>>- is_constructible<_T2, const _U2&&>,
>>+ is_constructible<_T2, _U2&&>,
>
>N.B. this fixes a bug in the line above, where const _U2&& is used in
>place of const _U2&.
>
>I'll create a testcase that tickles the bug and report it to bugzilla
>tomorrow.
This fails to compile because of that bug:
#include <utility>
struct X {
X(void* = 0) { }
X(const X&) = default;
X(const X&&) = delete;
};
struct move_only {
move_only() = default;
move_only(move_only&&) = default;
};
std::pair<move_only, X> p0(move_only(), 0);
std::pair<move_only, X> p1(move_only(), {});
The pair(U1&&, const T2&) constructor should be viable, but it fails
the _MoveCopyPair constraint check because X(const X&&) is deleted.
I'm not sure I care about this though. It would only work because of
those non-standard constructors which we're talking about deprecating.
I'm not very motivated to fix them so they accept this, when we're
going to deprecate them anyway.
More information about the Libstdc++
mailing list