diff options
author | Eric Fiselier <eric@efcs.ca> | 2016-08-29 01:43:41 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2016-08-29 01:43:41 +0000 |
commit | 1410a038446493d483b5e6c4098325b9af3d8896 (patch) | |
tree | 3ad1501d66036db6a69d06431e6ff3ea34777ed3 /libcxx | |
parent | 8abe7209ec5b57a9d6762705eb425af89729ebd1 (diff) |
Fix pair::operator=(TupleLike&&).
This assignment operator was previously broken since the SFINAE always resulted
in substitution failure. This caused assignments to turn into
copy construction + assignment.
This patch was originally committed as r279953 but was reverted due to warnings
in the test-suite. This new patch corrects those warnings.
Diffstat (limited to 'libcxx')
-rw-r--r-- | libcxx/include/utility | 2 | ||||
-rw-r--r-- | libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp | 140 |
2 files changed, 141 insertions, 1 deletions
diff --git a/libcxx/include/utility b/libcxx/include/utility index fbb06f33526..095748d861b 100644 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -515,7 +515,7 @@ struct _LIBCPP_TYPE_VIS_ONLY pair } template <class _Tuple, _EnableB< - _CheckTLC<_Tuple>::template __enable_assign() + _CheckTLC<_Tuple>::template __enable_assign<_Tuple>() > = false> _LIBCPP_INLINE_VISIBILITY pair& operator=(_Tuple&& __p) { diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp new file mode 100644 index 00000000000..ef7bebcf5c2 --- /dev/null +++ b/libcxx/test/std/utilities/utility/pairs/pairs.pair/assign_tuple.pass.cpp @@ -0,0 +1,140 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <utility> + +// template <class T1, class T2> struct pair + +// template<class U, class V> pair& operator=(tuple<U, V>&& p); + +#include <utility> +#include <tuple> +#include <array> +#include <memory> +#include <cassert> + +// Clang warns about missing braces when initializing std::array. +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-braces" +#endif + +struct CountingType { + static int constructed; + static int copy_constructed; + static int move_constructed; + static int assigned; + static int copy_assigned; + static int move_assigned; + static void reset() { + constructed = copy_constructed = move_constructed = 0; + assigned = copy_assigned = move_assigned = 0; + } + CountingType() : value(0) { ++constructed; } + CountingType(int v) : value(v) { ++constructed; } + CountingType(CountingType const& o) : value(o.value) { ++constructed; ++copy_constructed; } + CountingType(CountingType&& o) : value(o.value) { ++constructed; ++move_constructed; o.value = -1;} + + CountingType& operator=(CountingType const& o) { + ++assigned; + ++copy_assigned; + value = o.value; + return *this; + } + CountingType& operator=(CountingType&& o) { + ++assigned; + ++move_assigned; + value = o.value; + o.value = -1; + return *this; + } + int value; +}; +int CountingType::constructed; +int CountingType::copy_constructed; +int CountingType::move_constructed; +int CountingType::assigned; +int CountingType::copy_assigned; +int CountingType::move_assigned; + +int main() +{ + using C = CountingType; + { + using P = std::pair<int, C>; + using T = std::tuple<int, C>; + T t(42, C{42}); + P p(101, C{101}); + C::reset(); + p = t; + assert(C::constructed == 0); + assert(C::assigned == 1); + assert(C::copy_assigned == 1); + assert(C::move_assigned == 0); + assert(p.first == 42); + assert(p.second.value == 42); + } + { + using P = std::pair<int, C>; + using T = std::tuple<int, C>; + T t(42, -42); + P p(101, 101); + C::reset(); + p = std::move(t); + assert(C::constructed == 0); + assert(C::assigned == 1); + assert(C::copy_assigned == 0); + assert(C::move_assigned == 1); + assert(p.first == 42); + assert(p.second.value == -42); + } + { + using P = std::pair<C, C>; + using T = std::array<C, 2>; + T t = {42, -42}; + P p{101, 101}; + C::reset(); + p = t; + assert(C::constructed == 0); + assert(C::assigned == 2); + assert(C::copy_assigned == 2); + assert(C::move_assigned == 0); + assert(p.first.value == 42); + assert(p.second.value == -42); + } + { + using P = std::pair<C, C>; + using T = std::array<C, 2>; + T t = {42, -42}; + P p{101, 101}; + C::reset(); + p = t; + assert(C::constructed == 0); + assert(C::assigned == 2); + assert(C::copy_assigned == 2); + assert(C::move_assigned == 0); + assert(p.first.value == 42); + assert(p.second.value == -42); + } + { + using P = std::pair<C, C>; + using T = std::array<C, 2>; + T t = {42, -42}; + P p{101, 101}; + C::reset(); + p = std::move(t); + assert(C::constructed == 0); + assert(C::assigned == 2); + assert(C::copy_assigned == 0); + assert(C::move_assigned == 2); + assert(p.first.value == 42); + assert(p.second.value == -42); + } +} |