template<typename _Container>
[[__nodiscard__, __gnu__::__always_inline__]]
inline _GLIBCXX17_CONSTEXPR auto
- begin(_Container& __cont) -> decltype(__cont.begin())
+ begin(_Container& __cont) noexcept(noexcept(__cont.begin()))
+ -> decltype(__cont.begin())
{ return __cont.begin(); }
/**
template<typename _Container>
[[__nodiscard__, __gnu__::__always_inline__]]
inline _GLIBCXX17_CONSTEXPR auto
- begin(const _Container& __cont) -> decltype(__cont.begin())
+ begin(const _Container& __cont) noexcept(noexcept(__cont.begin()))
+ -> decltype(__cont.begin())
{ return __cont.begin(); }
/**
template<typename _Container>
[[__nodiscard__, __gnu__::__always_inline__]]
inline _GLIBCXX17_CONSTEXPR auto
- end(_Container& __cont) -> decltype(__cont.end())
+ end(_Container& __cont) noexcept(noexcept(__cont.end()))
+ -> decltype(__cont.end())
{ return __cont.end(); }
/**
template<typename _Container>
[[__nodiscard__, __gnu__::__always_inline__]]
inline _GLIBCXX17_CONSTEXPR auto
- end(const _Container& __cont) -> decltype(__cont.end())
+ end(const _Container& __cont) noexcept(noexcept(__cont.end()))
+ -> decltype(__cont.end())
{ return __cont.end(); }
/**
template<typename _Container>
[[nodiscard, __gnu__::__always_inline__]]
constexpr auto
- ssize(const _Container& __cont)
- noexcept(noexcept(__cont.size()))
+ ssize(const _Container& __cont) noexcept(noexcept(__cont.size()))
-> common_type_t<ptrdiff_t, make_signed_t<decltype(__cont.size())>>
{
using type = make_signed_t<decltype(__cont.size())>;
std::begin({1, 2, 3});
std::end({1, 2, 3});
}
+
+void
+test02()
+{
+ static constexpr std::initializer_list<int> il{1};
+ static_assert( std::begin(il) == il.begin() );
+ static_assert( std::end(il) == il.end() );
+ static_assert( noexcept(std::begin(il)) );
+ static_assert( noexcept(std::end(il)) );
+}
#include <iterator>
+#ifdef _GLIBCXX_RELEASE
+// Conditional noexcept on these functions is a libstdc++ extension
+# define NOTHROW(F) noexcept(noexcept(c.F()))
+#else
+# define NOTHROW(F)
+#endif
+
namespace std
{
- template<class C> auto begin(C& c) -> decltype(c.begin());
- template<class C> auto begin(const C& c) -> decltype(c.begin());
+ template<class C> auto begin(C& c) NOTHROW(begin) -> decltype(c.begin());
+ template<class C> auto begin(const C& c) NOTHROW(begin) -> decltype(c.begin());
- template<class C> auto end(C& c) -> decltype(c.end());
- template<class C> auto end(const C& c) -> decltype(c.end());
+ template<class C> auto end(C& c) NOTHROW(end) -> decltype(c.end());
+ template<class C> auto end(const C& c) NOTHROW(end) -> decltype(c.end());
template<class T, size_t N> T* begin(T (&array)[N]) noexcept;
template<class T, size_t N> T* end(T (&array)[N]) noexcept;
#include <iterator>
+#ifdef _GLIBCXX_RELEASE
+// Conditional noexcept on these functions is a libstdc++ extension
+# define NOTHROW(F) noexcept(noexcept(c.F()))
+#else
+# define NOTHROW(F)
+#endif
+
namespace std
{
- template<class C> auto begin(C& c) -> decltype(c.begin());
- template<class C> auto begin(const C& c) -> decltype(c.begin());
+ template<class C> auto begin(C& c) NOTHROW(begin) -> decltype(c.begin());
+ template<class C> auto begin(const C& c) NOTHROW(begin) -> decltype(c.begin());
- template<class C> auto end(C& c) -> decltype(c.end());
- template<class C> auto end(const C& c) -> decltype(c.end());
+ template<class C> auto end(C& c) NOTHROW(end) -> decltype(c.end());
+ template<class C> auto end(const C& c) NOTHROW(end) -> decltype(c.end());
template<class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept;
template<class T, size_t N> constexpr T* end(T (&array)[N]) noexcept;
#include <iterator>
+#ifdef _GLIBCXX_RELEASE
+// Conditional noexcept on these functions is a libstdc++ extension
+# define NOTHROW(F) noexcept(noexcept(c.F()))
+#else
+# define NOTHROW(F)
+#endif
+
namespace std
{
- template<class C> constexpr auto begin(C& c) -> decltype(c.begin());
- template<class C> constexpr auto begin(const C& c) -> decltype(c.begin());
+ template<class C> constexpr auto begin(C& c) NOTHROW(begin) -> decltype(c.begin());
+ template<class C> constexpr auto begin(const C& c) NOTHROW(begin) -> decltype(c.begin());
- template<class C> constexpr auto end(C& c) -> decltype(c.end());
- template<class C> constexpr auto end(const C& c) -> decltype(c.end());
+ template<class C> constexpr auto end(C& c) NOTHROW(end) -> decltype(c.end());
+ template<class C> constexpr auto end(const C& c) NOTHROW(end) -> decltype(c.end());
template<class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept;
template<class T, size_t N> constexpr T* end(T (&array)[N]) noexcept;
E e;
require_int( std::end(e) );
require_long( std::end(const_cast<const E&>(e)) );
+
+ static_assert( ! noexcept(std::begin(b)), "throws" );
+ static_assert( ! noexcept(std::begin(const_cast<const B&>(b))), "throws" );
+ static_assert( ! noexcept(std::end(e)), "throws" );
+ static_assert( ! noexcept(std::end(const_cast<const E&>(e))), "throws" );
+
+ struct S
+ {
+ int* begin() noexcept { return nullptr; }
+ int* begin() const noexcept { return nullptr; }
+ int* end() noexcept { return nullptr; }
+ int* end() const noexcept { return nullptr; }
+ };
+ S s;
+ static_assert( noexcept(std::begin(s)), "nothrow" );
+ static_assert( noexcept(std::begin(const_cast<const S&>(s))), "nothrow" );
+ static_assert( noexcept(std::end(s)), "nothrow" );
+ static_assert( noexcept(std::end(const_cast<const S&>(s))), "nothrow" );
}
static_assert( noexcept(std::rbegin(il)), "LWG 3537" );
static_assert( noexcept(std::rend(il)), "LWG 3537" );
}
+
+void
+test04()
+{
+ static int i[1]{};
+ static_assert( std::size(i) == 1 );
+ static_assert( noexcept(std::size(i)) );
+ static const int ci[2]{};
+ static_assert( std::size(ci) == 2 );
+ static_assert( noexcept(std::size(ci)) );
+ static constexpr std::initializer_list<int> il{1, 2, 3};
+ static_assert( std::size(il) == 3 );
+ struct Cont
+ {
+ constexpr unsigned size() const { return 4; }
+ };
+ constexpr Cont c;
+ static_assert( std::size(c) == 4 );
+}
+
+void
+test05()
+{
+ static int i[1]{};
+ static_assert( std::empty(i) == false );
+ static_assert( noexcept(std::size(i)) );
+ static const int ci[2]{};
+ static_assert( std::empty(ci) == false );
+ static_assert( noexcept(std::size(ci)) );
+ static constexpr std::initializer_list<int> il{1, 2, 3};
+ static_assert( std::empty(il) == false );
+ struct Cont
+ {
+ constexpr bool empty() const { return true; }
+ };
+ constexpr Cont c;
+ static_assert( std::empty(c) == true );
+}
+
+void
+test06()
+{
+ static int i[1]{};
+ static_assert( std::data(i) == i );
+ static_assert( noexcept(std::size(i)) );
+ static const int ci[2]{};
+ static_assert( std::data(ci) == ci );
+ static_assert( noexcept(std::size(ci)) );
+ static constexpr std::initializer_list<int> il{1, 2, 3};
+ static_assert( std::data(il) == il.begin() );
+ struct Cont
+ {
+ constexpr int* data() const { return nullptr; }
+ };
+ constexpr Cont c;
+ static_assert( std::data(c) == nullptr );
+}
{
struct Cont
{
- constexpr unsigned short size() const { return 3; }
+ constexpr unsigned short size() const noexcept { return 3; }
};
constexpr Cont c;
constexpr auto s = std::ssize(c);
const std::ptrdiff_t* check_type = &s;
static_assert(s == 3);
+
+#ifdef _GLIBCXX_RELEASE
+ static_assert( noexcept(std::ssize(c)) ); // This is a libstdc++ extension.
+#endif
}
void
constexpr auto s = std::ssize(c);
const long long* check_type = &s;
static_assert(s == 4);
+
+ static_assert( ! noexcept(std::ssize(c)) );
}