[libcxx-commits] [libcxx] 82c4701 - [libc++][nfc] SFINAE on pair/tuple assignment operators: LWG 2729.
via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Feb 19 13:25:47 PST 2021
Author: zoecarver
Date: 2021-02-19T13:25:34-08:00
New Revision: 82c4701d4e7e6c3bb879a5e98d660a126025b87a
URL: https://github.com/llvm/llvm-project/commit/82c4701d4e7e6c3bb879a5e98d660a126025b87a
DIFF: https://github.com/llvm/llvm-project/commit/82c4701d4e7e6c3bb879a5e98d660a126025b87a.diff
LOG: [libc++][nfc] SFINAE on pair/tuple assignment operators: LWG 2729.
This patch ensures that SFINAE is used to delete assignment operators in pair and tuple based on issue 2729.
Differential Review: https://reviews.llvm.org/D62454
Added:
Modified:
libcxx/docs/Cxx1zStatusIssuesStatus.csv
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Cxx1zStatusIssuesStatus.csv b/libcxx/docs/Cxx1zStatusIssuesStatus.csv
index 91fa59935829..383c3af652d3 100644
--- a/libcxx/docs/Cxx1zStatusIssuesStatus.csv
+++ b/libcxx/docs/Cxx1zStatusIssuesStatus.csv
@@ -232,7 +232,7 @@
"`2699 <https://wg21.link/LWG2699>`__","Missing restriction in [numeric.requirements]","Issaquah","|Complete|",""
"`2712 <https://wg21.link/LWG2712>`__","copy_file(from, to, ...) has a number of unspecified error conditions","Issaquah","|Complete|",""
"`2722 <https://wg21.link/LWG2722>`__","equivalent incorrectly specifies throws clause","Issaquah","|Complete|",""
-"`2729 <https://wg21.link/LWG2729>`__","Missing SFINAE on std::pair::operator=","Issaquah","",""
+"`2729 <https://wg21.link/LWG2729>`__","Missing SFINAE on std::pair::operator=","Issaquah","|Complete|",""
"`2732 <https://wg21.link/LWG2732>`__","Questionable specification of path::operator/= and path::append","Issaquah","|Complete|",""
"`2733 <https://wg21.link/LWG2733>`__","[fund.ts.v2] gcd / lcm and bool","Issaquah","|Complete|",""
"`2735 <https://wg21.link/LWG2735>`__","std::abs(short), std::abs(signed char) and others should return int instead of double in order to be compatible with C++98 and C","Issaquah","|Complete|",""
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
index 41940ec0ae91..8edb818d1976 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/const_pair.pass.cpp
@@ -17,6 +17,7 @@
#include <tuple>
#include <utility>
+#include <memory>
#include <cassert>
#include "test_macros.h"
@@ -32,6 +33,13 @@ int main(int, char**)
assert(std::get<0>(t1) == 2);
assert(std::get<1>(t1) == short('a'));
}
+ {
+ // test that the implicitly generated copy assignment operator
+ // is properly deleted
+ using T = std::tuple<int, int>;
+ using P = std::tuple<std::unique_ptr<int>, std::unique_ptr<int>>;
+ static_assert(!std::is_assignable<T, const P &>::value, "");
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
index 8803f29fab30..e02fc842ca22 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_copy.pass.cpp
@@ -34,6 +34,11 @@ struct D
explicit D(int i = 0) : B(i) {}
};
+struct NonAssignable {
+ NonAssignable& operator=(NonAssignable const&) = delete;
+ NonAssignable& operator=(NonAssignable&&) = delete;
+};
+
int main(int, char**)
{
{
@@ -87,6 +92,12 @@ int main(int, char**)
assert(std::get<0>(t) == 43);
assert(&std::get<0>(t) == &x);
}
+ {
+ using T = std::tuple<int, NonAssignable>;
+ using U = std::tuple<NonAssignable, int>;
+ static_assert(!std::is_assignable<T, U const&>::value, "");
+ static_assert(!std::is_assignable<U, T const&>::value, "");
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
index ec51c21a7d0b..39bcc5dd3609 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/convert_move.pass.cpp
@@ -45,6 +45,11 @@ struct E {
}
};
+struct NonAssignable {
+ NonAssignable& operator=(NonAssignable const&) = delete;
+ NonAssignable& operator=(NonAssignable&&) = delete;
+};
+
int main(int, char**)
{
{
@@ -108,6 +113,12 @@ int main(int, char**)
assert(std::get<0>(t) == 43);
assert(&std::get<0>(t) == &x);
}
+ {
+ using T = std::tuple<int, NonAssignable>;
+ using U = std::tuple<NonAssignable, int>;
+ static_assert(!std::is_assignable<T, U&&>::value, "");
+ static_assert(!std::is_assignable<U, T&&>::value, "");
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
index 91111336ba72..bbccd6754078 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/copy.pass.cpp
@@ -35,6 +35,10 @@ struct MoveAssignable {
MoveAssignable& operator=(MoveAssignable&&) = default;
};
+struct CopyAssignableInt {
+ CopyAssignableInt& operator=(int&) { return *this; }
+};
+
int main(int, char**)
{
{
@@ -89,8 +93,8 @@ int main(int, char**)
static_assert(!std::is_copy_assignable<T>::value, "");
}
{
- using T = std::tuple<int, NonAssignable>;
- static_assert(!std::is_copy_assignable<T>::value, "");
+ using T = std::tuple<int, NonAssignable>;
+ static_assert(!std::is_copy_assignable<T>::value, "");
}
{
using T = std::tuple<int, CopyAssignable>;
@@ -100,6 +104,21 @@ int main(int, char**)
using T = std::tuple<int, MoveAssignable>;
static_assert(!std::is_copy_assignable<T>::value, "");
}
+ {
+ using T = std::tuple<int, int, int>;
+ using P = std::pair<int, int>;
+ static_assert(!std::is_assignable<T, P>::value, "");
+ }
+ { // test const requirement
+ using T = std::tuple<CopyAssignableInt, CopyAssignableInt>;
+ using P = std::pair<int, int>;
+ static_assert(!std::is_assignable<T&, P const>::value, "");
+ }
+ {
+ using T = std::tuple<int, MoveAssignable>;
+ using P = std::pair<int, MoveAssignable>;
+ static_assert(!std::is_assignable<T&, P&>::value, "");
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
index e642f4a59e30..292cfc2ba321 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move.pass.cpp
@@ -105,8 +105,8 @@ int main(int, char**)
}
{
- using T = std::tuple<int, NonAssignable>;
- static_assert(!std::is_move_assignable<T>::value, "");
+ using T = std::tuple<int, NonAssignable>;
+ static_assert(!std::is_move_assignable<T>::value, "");
}
{
using T = std::tuple<int, MoveAssignable>;
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
index c60927f97aec..20315c01b111 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/move_pair.pass.cpp
@@ -37,6 +37,11 @@ struct D
explicit D(int i) : B(i) {}
};
+struct NonMoveAssignable {
+ NonMoveAssignable& operator=(NonMoveAssignable const&) = default;
+ NonMoveAssignable& operator=(NonMoveAssignable&&) = delete;
+};
+
int main(int, char**)
{
{
@@ -48,6 +53,16 @@ int main(int, char**)
assert(std::get<0>(t1) == 2);
assert(std::get<1>(t1)->id_ == 3);
}
+ {
+ using T = std::tuple<int, NonMoveAssignable>;
+ using P = std::pair<int, NonMoveAssignable>;
+ static_assert(!std::is_assignable<T&, P&&>::value, "");
+ }
+ {
+ using T = std::tuple<int, int, int>;
+ using P = std::pair<int, int>;
+ static_assert(!std::is_assignable<T&, P&&>::value, "");
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
index becf36e66cf3..fab9f6429088 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_const_pair_U_V.pass.cpp
@@ -20,6 +20,12 @@
#include "archetypes.h"
#endif
+struct CopyAssignableInt {
+ CopyAssignableInt& operator=(int&) { return *this; }
+};
+
+struct Unrelated {};
+
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<int, short> P1;
@@ -58,6 +64,18 @@ TEST_CONSTEXPR_CXX20 bool test() {
assert(p.second.value == -42);
}
#endif
+
+ { // test const requirement
+ using T = std::pair<CopyAssignableInt, CopyAssignableInt>;
+ using P = std::pair<int, int>;
+ static_assert(!std::is_assignable<T&, P const>::value, "");
+ }
+ {
+ using T = std::pair<int, Unrelated>;
+ using P = std::pair<Unrelated, int>;
+ static_assert(!std::is_assignable<T&, P&>::value, "");
+ static_assert(!std::is_assignable<P&, T&>::value, "");
+ }
return true;
}
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
index 94e30aec3332..253bd1b85d03 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_pair.pass.cpp
@@ -77,6 +77,10 @@ TEST_CONSTEXPR_CXX20 bool test() {
using P = std::pair<int, ConstexprTestTypes::MoveAssignOnly>;
static_assert(!std::is_copy_assignable<P>::value, "");
}
+ {
+ using P = std::pair<int, std::unique_ptr<int> >;
+ static_assert(!std::is_copy_assignable<P>::value, "");
+ }
{
using P = std::pair<int, Incomplete&>;
static_assert(!std::is_copy_assignable<P>::value, "");
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
index cc4e4f5c1108..7dbf98f01723 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair.pass.cpp
@@ -35,6 +35,11 @@ struct CountAssign {
}
};
+struct NotAssignable {
+ NotAssignable& operator=(NotAssignable const&) = delete;
+ NotAssignable& operator=(NotAssignable&&) = delete;
+};
+
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<ConstexprTestTypes::MoveOnly, int> P;
@@ -83,6 +88,11 @@ TEST_CONSTEXPR_CXX20 bool test() {
assert(p2.first.moved == 0);
assert(p2.first.copied == 0);
}
+ {
+ using T = std::pair<int, NotAssignable>;
+ using P = std::pair<int, NotAssignable>;
+ static_assert(!std::is_assignable<T, P&&>::value, "");
+ }
return true;
}
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
index 7267f7a2ef8b..cd0c39a0bb6c 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp
@@ -40,6 +40,10 @@ struct CountAssign {
}
};
+struct CopyAssignableInt {
+ CopyAssignableInt& operator=(int&) { return *this; }
+};
+
TEST_CONSTEXPR_CXX20 bool test() {
{
typedef std::pair<Derived, short> P1;
@@ -61,6 +65,12 @@ TEST_CONSTEXPR_CXX20 bool test() {
assert(t.second.moved == 0);
assert(t.second.copied == 0);
}
+ { // test const requirement
+ using T = std::pair<CopyAssignableInt, CopyAssignableInt>;
+ using P = std::pair<int, int>;
+ static_assert(!std::is_assignable<T, P&&>::value, "");
+ static_assert(!std::is_assignable<P, T&&>::value, "");
+ }
return true;
}
More information about the libcxx-commits
mailing list