+2020-02-05 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/iterator_concepts.h (iter_reference_t)
+ (iter_rvalue_reference_t, iter_common_reference_t, indirect_result_t):
+ Remove workarounds for PR c++/67704.
+ * testsuite/24_iterators/aliases.cc: New test.
+
2020-02-05 Patrick Palka <ppalka@redhat.com>
* include/bits/stl_iterator.h (move_iterator::move_iterator): Move __i
{
{ *__t } -> __can_reference;
};
-
- // FIXME: needed due to PR c++/67704
- template<__detail::__dereferenceable _Tp>
- struct __iter_ref
- {
- using type = decltype(*std::declval<_Tp&>());
- };
} // namespace __detail
- template<typename _Tp>
- using iter_reference_t = typename __detail::__iter_ref<_Tp>::type;
+ template<__detail::__dereferenceable _Tp>
+ using iter_reference_t = decltype(*std::declval<_Tp&>());
namespace ranges
{
} // inline namespace __cust
} // namespace ranges
- namespace __detail
- {
- // FIXME: needed due to PR c++/67704
- template<__detail::__dereferenceable _Tp>
- struct __iter_rvalue_ref
- { };
-
- template<__detail::__dereferenceable _Tp>
- requires requires(_Tp& __t)
- {
- { ranges::iter_move(__t) } -> __detail::__can_reference;
- }
- struct __iter_rvalue_ref<_Tp>
- { using type = decltype(ranges::iter_move(std::declval<_Tp&>())); };
-
- } // namespace __detail
-
- template<typename _Tp>
+ template<__detail::__dereferenceable _Tp>
+ requires requires(_Tp& __t)
+ { { ranges::iter_move(__t) } -> __detail::__can_reference; }
using iter_rvalue_reference_t
- = typename __detail::__iter_rvalue_ref<_Tp>::type;
+ = decltype(ranges::iter_move(std::declval<_Tp&>()));
template<typename> struct incrementable_traits { };
&& common_reference_with<iter_rvalue_reference_t<_In>&&,
const iter_value_t<_In>&>;
- namespace __detail
- {
- // FIXME: needed due to PR c++/67704
- template<readable _Tp>
- struct __iter_common_ref
- : common_reference<iter_reference_t<_Tp>, iter_value_t<_Tp>&>
- { };
- } // namespace __detail
-
- template<typename _Tp>
+ template<readable _Tp>
using iter_common_reference_t
- = typename __detail::__iter_common_ref<_Tp>::type;
+ = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
/// Requirements for writing a value into an iterator's referenced object.
template<typename _Out, typename _Tp>
&& strict_weak_order<_Fn&, iter_common_reference_t<_I1>,
iter_common_reference_t<_I2>>;
- namespace __detail
- {
- // FIXME: needed due to PR c++/67704
- template<typename _Fn, typename... _Is>
- struct __indirect_result
- { };
-
- template<typename _Fn, typename... _Is>
- requires (readable<_Is> && ...)
- && invocable<_Fn, iter_reference_t<_Is>...>
- struct __indirect_result<_Fn, _Is...>
- : invoke_result<_Fn, iter_reference_t<_Is>...>
- { };
- } // namespace __detail
-
template<typename _Fn, typename... _Is>
- using indirect_result_t = typename
- __detail::__indirect_result<_Fn, _Is...>::type;
+ requires (readable<_Is> && ...)
+ && invocable<_Fn, iter_reference_t<_Is>...>
+ using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>;
/// [projected], projected
template<readable _Iter, indirectly_regular_unary_invocable<_Iter> _Proj>
--- /dev/null
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <iterator>
+
+template<typename T>
+struct Dereferenceable { T operator*(); };
+
+template<typename T>
+ concept has_iter_reference
+ = requires { typename std::iter_reference_t<T>; };
+
+template<typename T, typename U>
+ concept is_iter_reference_for
+ = has_iter_reference<U> && std::same_as<T, std::iter_reference_t<U>>;
+
+static_assert(!has_iter_reference<Dereferenceable<void>>);
+static_assert(is_iter_reference_for<int, Dereferenceable<int>>);
+static_assert(is_iter_reference_for<int&, Dereferenceable<int&>>);
+static_assert(is_iter_reference_for<int&&, Dereferenceable<int&&>>);
+static_assert(is_iter_reference_for<int&, int*>);
+static_assert(is_iter_reference_for<const int&, const int*>);
+
+template<typename T>
+ concept has_iter_rvalue_reference
+ = requires { typename std::iter_rvalue_reference_t<T>; };
+
+template<typename T, typename U>
+ concept is_iter_rvalue_reference_for
+ = has_iter_rvalue_reference<U>
+ && std::same_as<T, std::iter_rvalue_reference_t<U>>;
+
+static_assert(!has_iter_rvalue_reference<Dereferenceable<void>>);
+static_assert(is_iter_rvalue_reference_for<int, Dereferenceable<int>>);
+static_assert(is_iter_rvalue_reference_for<int&&, Dereferenceable<int&>>);
+static_assert(is_iter_rvalue_reference_for<int&&, Dereferenceable<int&&>>);
+static_assert(is_iter_rvalue_reference_for<int&&, int*>);
+static_assert(is_iter_rvalue_reference_for<const int&&, const int*>);
+
+// These functions should be found by ADL. std::move is not applied to result.
+long iter_move(Dereferenceable<short>);
+long& iter_move(Dereferenceable<short&&>);
+static_assert(is_iter_rvalue_reference_for<long, Dereferenceable<short>>);
+static_assert(is_iter_rvalue_reference_for<long&, Dereferenceable<short&&>>);