libstdc++: Constrain reverse_iterator and move_iterator conversions [LWG 3435]
libstdc++-v3/ChangeLog: * include/bits/stl_iterator.h (reverse_iterator): Constrain converting constructor and converting assignment operator. Access source iterator's data member directly instead of calling base(). (move_iterator): Likewise. * testsuite/24_iterators/move_iterator/dr3435.cc: New test. * testsuite/24_iterators/reverse_iterator/dr3435.cc: New test.
This commit is contained in:
parent
259c3965b1
commit
a5a8a4e615
@ -129,6 +129,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
typename iterator_traits<_Iterator>::pointer,
|
||||
typename iterator_traits<_Iterator>::reference>
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Iter>
|
||||
friend class reverse_iterator;
|
||||
#endif
|
||||
|
||||
#if __cpp_lib_concepts
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3435. three_way_comparable_with<reverse_iterator<int*>, [...]>
|
||||
template<typename _Iter>
|
||||
static constexpr bool __convertible = !is_same_v<_Iter, _Iterator>
|
||||
&& convertible_to<const _Iter&, _Iterator>;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
_Iterator current;
|
||||
|
||||
@ -182,9 +195,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
* underlying %iterator can be converted to the type of @c current.
|
||||
*/
|
||||
template<typename _Iter>
|
||||
#if __cpp_lib_concepts
|
||||
requires __convertible<_Iter>
|
||||
#endif
|
||||
_GLIBCXX17_CONSTEXPR
|
||||
reverse_iterator(const reverse_iterator<_Iter>& __x)
|
||||
: current(__x.base()) { }
|
||||
: current(__x.current) { }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Iter>
|
||||
#if __cpp_lib_concepts
|
||||
requires __convertible<_Iter>
|
||||
&& assignable_from<_Iterator&, const _Iter&>
|
||||
#endif
|
||||
_GLIBCXX17_CONSTEXPR
|
||||
reverse_iterator&
|
||||
operator=(const reverse_iterator<_Iter>& __x)
|
||||
{
|
||||
current = __x.current;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @return @c current, the %iterator used for underlying work.
|
||||
@ -1270,6 +1301,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
using __base_ref = typename __traits_type::reference;
|
||||
#endif
|
||||
|
||||
template<typename _Iter2>
|
||||
friend class move_iterator;
|
||||
|
||||
#if __cpp_lib_concepts
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3435. three_way_comparable_with<reverse_iterator<int*>, [...]>
|
||||
template<typename _Iter2>
|
||||
static constexpr bool __convertible = !is_same_v<_Iter2, _Iterator>
|
||||
&& convertible_to<const _Iter2&, _Iterator>;
|
||||
#endif
|
||||
|
||||
public:
|
||||
using iterator_type = _Iterator;
|
||||
|
||||
@ -1303,15 +1345,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
: _M_current(std::move(__i)) { }
|
||||
|
||||
template<typename _Iter>
|
||||
#if __cpp_lib_concepts
|
||||
requires __convertible<_Iter>
|
||||
#endif
|
||||
_GLIBCXX17_CONSTEXPR
|
||||
move_iterator(const move_iterator<_Iter>& __i)
|
||||
: _M_current(__i.base()) { }
|
||||
: _M_current(__i._M_current) { }
|
||||
|
||||
template<typename _Iter>
|
||||
#if __cpp_lib_concepts
|
||||
requires __convertible<_Iter>
|
||||
&& assignable_from<_Iterator&, const _Iter&>
|
||||
#endif
|
||||
_GLIBCXX17_CONSTEXPR
|
||||
move_iterator& operator=(const move_iterator<_Iter>& __i)
|
||||
{
|
||||
_M_current = __i.base();
|
||||
_M_current = __i._M_current;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
37
libstdc++-v3/testsuite/24_iterators/move_iterator/dr3435.cc
Normal file
37
libstdc++-v3/testsuite/24_iterators/move_iterator/dr3435.cc
Normal file
@ -0,0 +1,37 @@
|
||||
// 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>
|
||||
#include <compare>
|
||||
|
||||
// LWG 3435. three_way_comparable_with<reverse_iterator<int*>, reverse_iterator<const int*>>
|
||||
// and
|
||||
// LWG 3265. move_iterator's conversions are more broken after P1207
|
||||
|
||||
using RI = std::move_iterator<int*>;
|
||||
using CRI = std::move_iterator<const int*>;
|
||||
|
||||
static_assert( std::three_way_comparable_with<RI, CRI> );
|
||||
|
||||
static_assert( std::is_convertible_v<const RI&, CRI> );
|
||||
static_assert( ! std::is_convertible_v<const CRI&, RI> );
|
||||
|
||||
static_assert( std::is_assignable_v<CRI, const RI&> );
|
||||
static_assert( ! std::is_assignable_v<RI, const CRI&> );
|
@ -0,0 +1,36 @@
|
||||
// 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>
|
||||
#include <compare>
|
||||
|
||||
// LWG 3435.
|
||||
// three_way_comparable_with<reverse_iterator<int*>, reverse_iterator<const int*>>
|
||||
|
||||
using RI = std::reverse_iterator<int*>;
|
||||
using CRI = std::reverse_iterator<const int*>;
|
||||
|
||||
static_assert( std::three_way_comparable_with<RI, CRI> );
|
||||
|
||||
static_assert( std::is_convertible_v<const RI&, CRI> );
|
||||
static_assert( ! std::is_convertible_v<const CRI&, RI> );
|
||||
|
||||
static_assert( std::is_assignable_v<CRI, const RI&> );
|
||||
static_assert( ! std::is_assignable_v<RI, const CRI&> );
|
Loading…
Reference in New Issue
Block a user