libstdc++: Add noexcept to std::begin etc as per LWG 2280 and 3537
This implements the proposed changes for LWG 3537 (which we're allowed to do as an extension whatever the outcome of the issue). I noticed we didn't implement LWG 2280 completely, as the std::begin and std::end overloads for arrays were not noexcept. libstdc++-v3/ChangeLog: * include/bits/range_access.h (begin(T (&)[N]), end(T (&)[N])): Add missing 'noexcept' as per LWG 2280. (rbegin(T (&)[N]), rend(T (&)[N]), rbegin(initializer_list<T>)) (rend(initializer_list<T>)): Add 'noexcept' as per LWG 3537. * testsuite/24_iterators/range_access/range_access.cc: Check for expected noexcept specifiers. Check result types of generic std::begin and std::end overloads. * testsuite/24_iterators/range_access/range_access_cpp14.cc: Check for expected noexcept specifiers. * testsuite/24_iterators/range_access/range_access_cpp17.cc: Likewise.
This commit is contained in:
parent
87e3c2ef68
commit
00b46c00c8
@ -87,7 +87,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX14_CONSTEXPR _Tp*
|
||||
begin(_Tp (&__arr)[_Nm])
|
||||
begin(_Tp (&__arr)[_Nm]) noexcept
|
||||
{ return __arr; }
|
||||
|
||||
/**
|
||||
@ -97,7 +97,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX14_CONSTEXPR _Tp*
|
||||
end(_Tp (&__arr)[_Nm])
|
||||
end(_Tp (&__arr)[_Nm]) noexcept
|
||||
{ return __arr + _Nm; }
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
@ -178,7 +178,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
|
||||
rbegin(_Tp (&__arr)[_Nm])
|
||||
rbegin(_Tp (&__arr)[_Nm]) noexcept
|
||||
{ return reverse_iterator<_Tp*>(__arr + _Nm); }
|
||||
|
||||
/**
|
||||
@ -188,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
|
||||
rend(_Tp (&__arr)[_Nm])
|
||||
rend(_Tp (&__arr)[_Nm]) noexcept
|
||||
{ return reverse_iterator<_Tp*>(__arr); }
|
||||
|
||||
/**
|
||||
@ -198,7 +198,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
|
||||
rbegin(initializer_list<_Tp> __il)
|
||||
rbegin(initializer_list<_Tp> __il) noexcept
|
||||
{ return reverse_iterator<const _Tp*>(__il.end()); }
|
||||
|
||||
/**
|
||||
@ -208,7 +208,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Tp>
|
||||
inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
|
||||
rend(initializer_list<_Tp> __il)
|
||||
rend(initializer_list<_Tp> __il) noexcept
|
||||
{ return reverse_iterator<const _Tp*>(__il.begin()); }
|
||||
|
||||
/**
|
||||
|
@ -27,4 +27,34 @@ test01()
|
||||
int arr[3] = {1, 2, 3};
|
||||
std::begin(arr);
|
||||
std::end(arr);
|
||||
|
||||
static_assert( noexcept(std::begin(arr)), "LWG 2280" );
|
||||
static_assert( noexcept(std::end(arr)), "LWG 2280" );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
extern void require_int(int*);
|
||||
extern void require_long(long*);
|
||||
|
||||
struct B
|
||||
{
|
||||
int* begin() { return nullptr; }
|
||||
long* begin() const { return nullptr; }
|
||||
};
|
||||
|
||||
B b;
|
||||
require_int( std::begin(b) );
|
||||
require_long( std::begin(const_cast<const B&>(b)) );
|
||||
|
||||
struct E
|
||||
{
|
||||
int* end() { return nullptr; }
|
||||
long* end() const { return nullptr; }
|
||||
};
|
||||
|
||||
E e;
|
||||
require_int( std::end(e) );
|
||||
require_long( std::end(const_cast<const E&>(e)) );
|
||||
}
|
||||
|
@ -39,10 +39,21 @@ void
|
||||
test02()
|
||||
{
|
||||
static int i[1];
|
||||
// LWG 2280
|
||||
constexpr auto b __attribute__((unused)) = std::begin(i);
|
||||
constexpr auto e __attribute__((unused)) = std::end(i);
|
||||
constexpr auto cb __attribute__((unused)) = std::cbegin(i);
|
||||
constexpr auto ce __attribute__((unused)) = std::cend(i);
|
||||
|
||||
// LWG 2280
|
||||
static_assert( noexcept(std::begin(i)), "LWG 2280" );
|
||||
static_assert( noexcept(std::end(i)), "LWG 2280" );
|
||||
static_assert( noexcept(std::cbegin(i)), "LWG 2280" );
|
||||
static_assert( noexcept(std::cend(i)), "LWG 2280" );
|
||||
|
||||
// LWG 3537
|
||||
static_assert( noexcept(std::rbegin(i)), "LWG 3537" );
|
||||
static_assert( noexcept(std::rend(i)), "LWG 3537" );
|
||||
}
|
||||
|
||||
void
|
||||
@ -55,6 +66,10 @@ test03()
|
||||
VERIFY(std::rend(il) == std::reverse_iterator<const int*>(il.begin()));
|
||||
VERIFY(std::crbegin(il) == std::reverse_iterator<const int*>(il.end()));
|
||||
VERIFY(std::crend(il) == std::reverse_iterator<const int*>(il.begin()));
|
||||
|
||||
// LWG 3537
|
||||
static_assert( noexcept(std::rbegin(il)), "LWG 3537" );
|
||||
static_assert( noexcept(std::rend(il)), "LWG 3537" );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -41,6 +41,16 @@ test02()
|
||||
static int i[] = { 1, 2 };
|
||||
static_assert(std::distance(std::begin(i), std::end(i)) == 2);
|
||||
static_assert(std::distance(std::cbegin(i), std::cend(i)) == 2);
|
||||
|
||||
// LWG 2280
|
||||
static_assert( noexcept(std::begin(i)), "LWG 2280" );
|
||||
static_assert( noexcept(std::end(i)), "LWG 2280" );
|
||||
static_assert( noexcept(std::cbegin(i)), "LWG 2280" );
|
||||
static_assert( noexcept(std::cend(i)), "LWG 2280" );
|
||||
|
||||
// LWG 3537
|
||||
static_assert( noexcept(std::rbegin(i)), "LWG 3537" );
|
||||
static_assert( noexcept(std::rend(i)), "LWG 3537" );
|
||||
}
|
||||
|
||||
void
|
||||
@ -54,4 +64,8 @@ test03()
|
||||
static_assert(std::rend(il) == reverse_iterator<const int*>(il.begin()));
|
||||
static_assert(std::crbegin(il) == reverse_iterator<const int*>(il.end()));
|
||||
static_assert(std::crend(il) == reverse_iterator<const int*>(il.begin()));
|
||||
|
||||
// LWG 3537
|
||||
static_assert( noexcept(std::rbegin(il)), "LWG 3537" );
|
||||
static_assert( noexcept(std::rend(il)), "LWG 3537" );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user