diff options
| author | Eric Fiselier <eric@efcs.ca> | 2016-07-11 19:57:13 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2016-07-11 19:57:13 +0000 |
| commit | 0774aa96dc60c889a54d4d22850526d999f491a3 (patch) | |
| tree | 27a6fbee6bd4f8efdde05df69fe6c13de634cda4 /libcxx | |
| parent | faaeaaf0d8ee2d195ac1d3ba2c399cbaaa3944d6 (diff) | |
| download | bcm5719-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_traits | 13 | ||||
| -rw-r--r-- | libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_swappable.pass.cpp | 21 |
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>, ""); |

