2016-07-31 Jonathan Wakely <jwakely@redhat.com>
+ PR libstdc++/72745
+ * include/std/array (get): Use positive message for static assertions.
+ * include/std/functional (_Safe_tuple_element_t): Fix indentation.
+ * include/std/tuple (tuple_element<I, tuple<>>): Add partial
+ specialization for invalid indices, with static assertion.
+ * testsuite/20_util/tuple/element_access/get_neg.cc: New test.
+
* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Move
dg-error to relevant line.
* testsuite/20_util/headers/type_traits/types_std_c++0x_neg.cc:
constexpr _Tp&
get(array<_Tp, _Nm>& __arr) noexcept
{
- static_assert(_Int < _Nm, "index is out of bounds");
+ static_assert(_Int < _Nm, "array index is within bounds");
return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
_S_ref(__arr._M_elems, _Int);
}
constexpr _Tp&&
get(array<_Tp, _Nm>&& __arr) noexcept
{
- static_assert(_Int < _Nm, "index is out of bounds");
+ static_assert(_Int < _Nm, "array index is within bounds");
return std::move(_GLIBCXX_STD_C::get<_Int>(__arr));
}
constexpr const _Tp&
get(const array<_Tp, _Nm>& __arr) noexcept
{
- static_assert(_Int < _Nm, "index is out of bounds");
+ static_assert(_Int < _Nm, "array index is within bounds");
return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::
_S_ref(__arr._M_elems, _Int);
}
// Like tuple_element_t but SFINAE-friendly.
- template<std::size_t __i, typename _Tuple>
- using _Safe_tuple_element_t
- = typename enable_if<(__i < tuple_size<_Tuple>::value),
- tuple_element<__i, _Tuple>>::type::type;
+ template<std::size_t __i, typename _Tuple>
+ using _Safe_tuple_element_t
+ = typename enable_if<(__i < tuple_size<_Tuple>::value),
+ tuple_element<__i, _Tuple>>::type::type;
/**
* Maps an argument to bind() into an actual argument to the bound
};
+ /// class tuple_size
+ template<typename... _Elements>
+ struct tuple_size<tuple<_Elements...>>
+ : public integral_constant<std::size_t, sizeof...(_Elements)> { };
+
+#if __cplusplus > 201402L
+ template <typename _Tp>
+ constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
+#endif
+
/**
* Recursive case for tuple_element: strip off the first element in
* the tuple and retrieve the (i-1)th element of the remaining tuple.
typedef _Head type;
};
- /// class tuple_size
- template<typename... _Elements>
- struct tuple_size<tuple<_Elements...>>
- : public integral_constant<std::size_t, sizeof...(_Elements)> { };
-
-#if __cplusplus > 201402L
- template <typename _Tp>
- constexpr size_t tuple_size_v = tuple_size<_Tp>::value;
-#endif
+ /**
+ * Error case for tuple_element: invalid index.
+ */
+ template<size_t __i>
+ struct tuple_element<__i, tuple<>>
+ {
+ static_assert(__i < tuple_size<tuple<>>::value,
+ "tuple index is in range");
+ };
template<std::size_t __i, typename _Head, typename... _Tail>
constexpr _Head&
--- /dev/null
+// Copyright (C) 2016 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 "-fno-show-column" }
+// { dg-do compile { target c++14 } }
+// { dg-error "in range" "" { target *-*-* } 1279 }
+
+#include <tuple>
+
+void
+test01()
+{
+ using test_type = std::tuple<>;
+ test_type t;
+ std::get<0>(t); // { dg-error "no match" }
+ std::get<0>(const_cast<const test_type&>(t)); // { dg-error "no match" }
+ std::get<0>(static_cast<test_type&&>(t)); // { dg-error "no match" }
+ std::get<5>(t); // { dg-error "no match" }
+ std::get<5>(const_cast<const test_type&>(t)); // { dg-error "no match" }
+ std::get<5>(static_cast<test_type&&>(t)); // { dg-error "no match" }
+}
+
+void
+test02()
+{
+ using test_type = std::tuple<int>;
+ test_type t;
+ std::get<1>(t); // { dg-error "no match" }
+ std::get<1>(const_cast<const test_type&>(t)); // { dg-error "no match" }
+ std::get<1>(static_cast<test_type&&>(t)); // { dg-error "no match" }
+ std::get<5>(t); // { dg-error "no match" }
+ std::get<5>(const_cast<const test_type&>(t)); // { dg-error "no match" }
+ std::get<5>(static_cast<test_type&&>(t)); // { dg-error "no match" }
+}
+
+void
+test03()
+{
+ using test_type = std::tuple<int, int, int, int>;
+ test_type t;
+ std::get<5>(t); // { dg-error "no match" }
+ std::get<5>(const_cast<const test_type&>(t)); // { dg-error "no match" }
+ std::get<5>(static_cast<test_type&&>(t)); // { dg-error "no match" }
+ std::get<6>(t); // { dg-error "no match" }
+ std::get<6>(const_cast<const test_type&>(t)); // { dg-error "no match" }
+ std::get<6>(static_cast<test_type&&>(t)); // { dg-error "no match" }
+}