I noticed the following behavior by accident (missed catching by reference), but I couldn't find information that, if I knew it before hand, would have allowed me to predict it.
With the minimal example
#include <iostream>
#include <stdexcept>
int main()
{
try
{
// Added this and the next line to check that the exception
// created has already the what() set to the input string.
std::out_of_range d("Out of range exception");
std::cout << "d.what() = " << d.what() << std::endl;
throw d;
}
catch (std::exception e) // Captured by value
{
std::cout << e.what() << std::endl;
}
}
If I compile it with g++ -std=c++17
and with Visual C++ I get different behaviors. With the first it prints d.what() = Out of range exception\nstd::exception
, while the second it prints d.what() = Out of range exception\nOut of range exception
.
In principle there could be slicing when the std::out_of_range
is captured by value and converted to the std::exception
type. This means that I could expect not getting the same behavior as an object from std::out_of_range
object when printing its what()
.
Question: The part that I don't know how to explain is getting different behaviors for the two compilers. Is this because this slicing is undefined behavior in the C++ standarization, or is it that one of these two compilers is not complying with it?
Extra observation: I just noticed that in this link there is no mention of the class std::exception
having a constructor that inputs a const char* const &
, while in the Microsoft website they include it. My accidental example shows that they indeed implemented these classes differently. My question is still whether they were allowed (if this behavior is undefined) or if one of them is not complying and which one.