29

Does anyone know what the following compilation warning: catching polymorphic type ‘class std::out_of_range’ by value [-Wcatch-value=] warning means and how to correct it? I copied this code block literally out of Stroustrup's C++ 4th Edition. Thank you

#include <iostream>
#include <vector>
#include <list>
using std::vector;
using std::list;
using std::cout;

template <typename T>
class Vec : public vector<T> {
 public:
  using vector<T>::vector;  // constructor

  T& operator[](int i) { return vector<T>::at(i); }
  const T& operator[](int i) const { return vector<T>::at(i); }
};

int main(int argc, char* argv[]) {
  vector<int> v0 = {0, 1, 2};
  Vec<int> v1 = {0, 1, 2};

  cout << v0[v0.size()] << '\n';  // no error

  try {
    cout << v1[v1.size()];  // out of range
  } catch (std::out_of_range) {
    cout << "tried out of range" << '\n';
  }

  return 0;
}

Error:

$ g++ -Wall -pedantic -std=c++11 test69.cc && ./a.out
test69.cc: In function ‘int main(int, char**)’:
test69.cc:32:17: warning: catching polymorphic type ‘class std::out_of_range’ by value [-Wcatch-value=]
   } catch (std::out_of_range) {
                 ^~~~~~~~~~~~
0
tried out of range
David G
  • 94,763
  • 41
  • 167
  • 253
notaorb
  • 1,944
  • 1
  • 8
  • 18
  • 4
    It's suggesting that you catch a reference: `catch (std::out_of_range&)` [catching std::exception by reference?](//stackoverflow.com/a/6756040) – 001 May 26 '20 at 19:57
  • 4
    Catch by const-reference instead, since you are not modifying the object, `catch (std::out_of_range const&)`. – Eljay May 26 '20 at 19:58
  • 2
    It means that you'll only ever catch a `std::out_of_range`, even if something derived was thrown. This is called "slicing" and can be dangerous: https://stackoverflow.com/questions/274626/what-is-object-slicing – alter_igel May 26 '20 at 19:58
  • Almost *always* catch exceptions by `const &`. – Jesper Juhl May 26 '20 at 20:06

2 Answers2

37

You should modify that to

catch (std::out_of_range const&)

The message is warning you that polymorphism only works with references and pointers.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
25

If you look at the C++ Core Guidelines, you can find

E.15: Catch exceptions from a hierarchy by reference

This is exactly your case. By catching a value, you are effectively using just the base class of the exception thrown (regardless of the type actually thrown). Instead, catch by reference (or const reference, if you don't plan on modifying the exception), to retain the polymorphic behaviour.

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185