summaryrefslogtreecommitdiffstats
path: root/libcxx
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-07-11 19:57:13 +0000
committerEric Fiselier <eric@efcs.ca>2016-07-11 19:57:13 +0000
commit0774aa96dc60c889a54d4d22850526d999f491a3 (patch)
tree27a6fbee6bd4f8efdde05df69fe6c13de634cda4 /libcxx
parentfaaeaaf0d8ee2d195ac1d3ba2c399cbaaa3944d6 (diff)
downloadbcm5719-llvm-0774aa96dc60c889a54d4d22850526d999f491a3.tar.gz
bcm5719-llvm-0774aa96dc60c889a54d4d22850526d999f491a3.zip
Allow is_swappable to SFINAE on deleted/ambiguous swap functions
llvm-svn: 275094
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/include/type_traits13
-rw-r--r--libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp21
2 files changed, 30 insertions, 4 deletions
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index a8b0bd067d5..821a73c764d 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -4446,15 +4446,20 @@ iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b)
namespace __detail
{
// ALL generic swap overloads MUST already have a declaration available at this point.
-using _VSTD::swap;
-__nat swap(__any, __any);
template <class _Tp, class _Up = _Tp,
bool _NotVoid = !is_void<_Tp>::value && !is_void<_Up>::value>
struct __swappable_with
{
- typedef decltype(swap(_VSTD::declval<_Tp>(), _VSTD::declval<_Up>())) __swap1;
- typedef decltype(swap(_VSTD::declval<_Up>(), _VSTD::declval<_Tp>())) __swap2;
+ template <class _LHS, class _RHS>
+ static decltype(swap(_VSTD::declval<_LHS>(), _VSTD::declval<_RHS>()))
+ __test_swap(int);
+ template <class, class>
+ static __nat __test_swap(long);
+
+ // Extra parens are needed for the C++03 definition of decltype.
+ typedef decltype((__test_swap<_Tp, _Up>(0))) __swap1;
+ typedef decltype((__test_swap<_Up, _Tp>(0))) __swap2;
static const bool value = !is_same<__swap1, __nat>::value
&& !is_same<__swap2, __nat>::value;
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp
index 9d01128379a..b17ca76fd58 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp
@@ -49,8 +49,21 @@ struct M {
void swap(M&&, M&&) {}
+struct DeletedSwap {
+ friend void swap(DeletedSwap&, DeletedSwap&) = delete;
+};
+
} // namespace MyNS
+namespace MyNS2 {
+
+struct AmbiguousSwap {};
+
+template <class T>
+void swap(T&, T&) {}
+
+} // end namespace MyNS2
+
int main()
{
using namespace MyNS;
@@ -70,6 +83,14 @@ int main()
static_assert(!std::is_swappable<int() &>::value, "");
}
{
+ // test that a deleted swap is correctly handled.
+ static_assert(!std::is_swappable<DeletedSwap>::value, "");
+ }
+ {
+ // test that a swap with ambiguous overloads is handled correctly.
+ static_assert(!std::is_swappable<MyNS2::AmbiguousSwap>::value, "");
+ }
+ {
// test for presence of is_swappable_v
static_assert(std::is_swappable_v<int>, "");
static_assert(!std::is_swappable_v<M>, "");
OpenPOWER on IntegriCloud