diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -18,8 +18,8 @@ "`P1425R4 `__","LWG","Iterators pair constructors for stack and queue","June 2021","","" "`P1518R2 `__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0" "`P1659R3 `__","LWG","starts_with and ends_with","June 2021","","" -"`P1951R1 `__","LWG","Default Arguments for pair Forwarding Constructor","June 2021","","" +"`P1951R1 `__","LWG","Default Arguments for pair Forwarding Constructor","June 2021","|Complete|","14.0" "`P1989R2 `__","LWG","Range constructor for std::string_view","June 2021","","" "`P2136R3 `__","LWG","invoke_r","June 2021","","" "`P2166R1 `__","LWG","A Proposal to Prohibit std::basic_string and std::basic_string_view construction from nullptr","June 2021","|Complete|","13.0" "","","","","","" \ No newline at end of file diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -24,7 +24,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD - #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) template struct __non_trivially_copyable_base { @@ -167,7 +166,7 @@ is_nothrow_copy_constructible::value) : first(__t1), second(__t2) {} - template() >::type* = nullptr> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 @@ -176,7 +175,7 @@ is_nothrow_constructible::value)) : first(_VSTD::forward<_U1>(__u1)), second(_VSTD::forward<_U2>(__u2)) {} - template() >::type* = nullptr> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 diff --git a/libcxx/include/utility b/libcxx/include/utility --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -79,7 +79,7 @@ pair(pair&&) = default; explicit(see-below) constexpr pair(); explicit(see-below) pair(const T1& x, const T2& y); // constexpr in C++14 - template explicit(see-below) pair(U&& x, V&& y); // constexpr in C++14 + template explicit(see-below) pair(U&& x, V&& y);// constexpr in C++14 template explicit(see-below) pair(const pair& p); // constexpr in C++14 template explicit(see-below) pair(pair&& p); // constexpr in C++14 template diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp --- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/U_V.pass.cpp @@ -12,12 +12,12 @@ // template struct pair -// template pair(U&& x, V&& y); +// template pair(U&& x, V&& y); #include -#include #include +#include #include "archetypes.h" #include "test_convertible.h" @@ -47,6 +47,24 @@ int value; }; +template ({}, {}))> +constexpr bool can_construct_with_brace_init(int) { return true; } +template +constexpr bool can_construct_with_brace_init(...) { return false; } + +#if TEST_STD_VER >= 17 // CTAD isn't supported before C++17 +template +constexpr bool can_construct_with_ctad_brace_init(int) { return true; } +template +constexpr bool can_construct_with_ctad_brace_init(...) { return false; } +#endif + +struct BraceInit { BraceInit() = default; }; +struct NoBraceInit { NoBraceInit(int); }; +struct ExplicitBraceInit { explicit ExplicitBraceInit() = default; }; + +constexpr int explicit_vs_implicit_brace_init(std::pair) { return 1; } +constexpr int explicit_vs_implicit_brace_init(std::pair) { return 2; } int main(int, char**) { @@ -99,5 +117,60 @@ } #endif +#if TEST_STD_VER > 20 || defined(_LIBCPP_VERSION) + // Test support for http://wg21.link/P1951, default arguments for pair's constructor. + // Note that libc++ applies this in all standard modes. + { + // Explicit constructor + { + std::pair p1(42, {}); + assert(p1.first.value == 42); + + std::pair p2{42, {}}; + assert(p2.first.value == 42); + } + { + std::pair p1({}, 42); + assert(p1.second.value == 42); + + std::pair p2{{}, 42}; + assert(p2.second.value == 42); + } + { + std::pair p{{}, {}}; (void)p; + } + + // Implicit constructor + { + std::pair p = {42, {}}; + assert(p.first.value == 42); + } + { + std::pair p = {{}, 42}; + assert(p.second.value == 42); + } + { + std::pair p = {{}, {}}; (void)p; + } + + // SFINAE-friendliness of some invalid cases + { + static_assert( can_construct_with_brace_init(0), ""); + static_assert(!can_construct_with_brace_init(0), ""); + +#if TEST_STD_VER >= 17 + // CTAD with {} should never work, since we can't possibly deduce the types + static_assert(!can_construct_with_ctad_brace_init(0), ""); + static_assert(!can_construct_with_ctad_brace_init(0), ""); +#endif + } + + // Make sure there is no ambiguity between the explicit and the non-explicit constructors + { + assert(explicit_vs_implicit_brace_init({{}, {}}) == 2); + } + } +#endif + return 0; }