diff options
author | Konstantin Varlamov <varconst@apple.com> | 2022-07-20 13:17:25 -0700 |
---|---|---|
committer | Konstantin Varlamov <varconst@apple.com> | 2022-07-20 13:19:00 -0700 |
commit | bc4d2e70518476f0a445761d43fee8b9e6670368 (patch) | |
tree | 3a487e0c0c780179d00170eee5414461c3149809 | |
parent | 2ac7b142b12f66ce91c98177f8d7d942ed4cc94c (diff) |
[libc++] Fix `_IterOps::__iter_move` to support proxy iterators.
The return type was specified incorrectly for proxy iterators that
define `reference` to be a class that implicitly converts to
`value_type`. `__iter_move` would end up returning an object of type
`reference` which would then implicitly convert to `value_type`; thus,
the function will return a `value_type&&` rvalue reference to the local
temporary.
Differential Revision: https://reviews.llvm.org/D130197
-rw-r--r-- | libcxx/include/__algorithm/iterator_operations.h | 6 | ||||
-rw-r--r-- | libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_proxy.pass.cpp | 27 |
2 files changed, 31 insertions, 2 deletions
diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h index 03dd2c41e94a..a3840594b8ae 100644 --- a/libcxx/include/__algorithm/iterator_operations.h +++ b/libcxx/include/__algorithm/iterator_operations.h @@ -66,8 +66,10 @@ struct _IterOps<_ClassicAlgPolicy> { // iter_move template <class _Iter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 - // Declaring the return type is necessary for the C++03 mode (which doesn't support placeholder return types). - static typename iterator_traits<__uncvref_t<_Iter> >::value_type&& __iter_move(_Iter&& __i) { + // Declaring the return type is necessary for C++03, so we basically mirror what `decltype(auto)` would deduce. + static typename remove_reference< + typename iterator_traits<__uncvref_t<_Iter> >::reference + >::type&& __iter_move(_Iter&& __i) { return std::move(*std::forward<_Iter>(__i)); } diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_proxy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_proxy.pass.cpp new file mode 100644 index 000000000000..4dc872566d92 --- /dev/null +++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_proxy.pass.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// <algorithm> + +#include <algorithm> +#include <cassert> +#include <vector> + +void test() { + // TODO: use a custom proxy iterator instead of (or in addition to) `vector<bool>`. + std::vector<bool> v(5, false); + v[1] = true; v[3] = true; + std::sort(v.begin(), v.end()); + assert(std::is_sorted(v.begin(), v.end())); +} + +int main(int, char**) { + test(); + + return 0; +} |