]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Improve diagnostics for std::get with invalid tuple index
authorJonathan Wakely <jwakely@redhat.com>
Fri, 16 Jul 2021 19:59:43 +0000 (20:59 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 16 Jul 2021 21:24:34 +0000 (22:24 +0100)
This adds a deleted overload of std::get<I>(const tuple<Types...>&).
Invalid calls with an out of range index will match the deleted overload
and give a single, clear error about calling a deleted function, instead
of overload resolution errors for every std::get overload in the
library.

This changes the current output of 15+ errors (plus notes and associated
header context) into just two errors (plus context):

error: static assertion failed: tuple index must be in range
error: use of deleted function 'constexpr std::__enable_if_t<(__i >= sizeof... (_Types))> std::get(const std::tuple<_Types ...>&) [with long unsigned int __i = 1; _Elements = {int}; std::__enable_if_t<(__i >= sizeof... (_Types))> = void]'

This seems like a nice improvement, although PR c++/66968 means that
"_Types" is printed in the signature rather than "_Elements".

Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:

* include/std/tuple (get<I>): Add deleted overload for bad
index.
* testsuite/20_util/tuple/element_access/get_neg.cc: Adjust
expected errors.

libstdc++-v3/include/std/tuple
libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc

index 6953f8715d74488ecf124bed1e6f5ad5fe98ac9a..8ee0d2f1ef55f68740960e3873777f69a97b3b84 100644 (file)
@@ -1406,6 +1406,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return std::forward<const __element_type>(std::__get_helper<__i>(__t));
     }
 
+  /// @cond undocumented
+  // Deleted overload chosen for invalid indices.
+  template<size_t __i, typename... _Elements>
+    constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
+    get(const tuple<_Elements...>&) = delete;
+  /// @endcond
+
 #if __cplusplus >= 201402L
 
 #define __cpp_lib_tuples_by_type 201304
index cd850fdc21b59adf7bb9b0780198b429ae7c5991..225bb6245a6d0e35a0b441cb01b55db1dcf5b5e4 100644 (file)
@@ -25,12 +25,12 @@ 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" }
+  std::get<0>(t);                              // { dg-error "deleted" }
+  std::get<0>(const_cast<const test_type&>(t));        // { dg-error "deleted" }
+  std::get<0>(static_cast<test_type&&>(t));    // { dg-error "deleted" }
+  std::get<5>(t);                              // { dg-error "deleted" }
+  std::get<5>(const_cast<const test_type&>(t));        // { dg-error "deleted" }
+  std::get<5>(static_cast<test_type&&>(t));    // { dg-error "deleted" }
 }
 
 void
@@ -38,12 +38,12 @@ 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" }
+  std::get<1>(t);                              // { dg-error "deleted" }
+  std::get<1>(const_cast<const test_type&>(t));        // { dg-error "deleted" }
+  std::get<1>(static_cast<test_type&&>(t));    // { dg-error "deleted" }
+  std::get<5>(t);                              // { dg-error "deleted" }
+  std::get<5>(const_cast<const test_type&>(t));        // { dg-error "deleted" }
+  std::get<5>(static_cast<test_type&&>(t));    // { dg-error "deleted" }
 }
 
 void
@@ -51,15 +51,12 @@ 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" }
+  std::get<5>(t);                              // { dg-error "deleted" }
+  std::get<5>(const_cast<const test_type&>(t));        // { dg-error "deleted" }
+  std::get<5>(static_cast<test_type&&>(t));    // { dg-error "deleted" }
+  std::get<6>(t);                              // { dg-error "deleted" }
+  std::get<6>(const_cast<const test_type&>(t));        // { dg-error "deleted" }
+  std::get<6>(static_cast<test_type&&>(t));    // { dg-error "deleted" }
 }
 
-// { dg-prune-output "tuple index must be in range" }
-// { dg-prune-output "no type named .type" }
-// { dg-prune-output "type/value mismatch" }
-// { dg-prune-output "use of deleted function" }
+// { dg-error "tuple index must be in range" "" { target *-*-* } 0 }