Да кажем, че имам този клас изключения:
struct MyException : public std::exception
{
MyException(const std::exception &exc) : std::exception(exc)
{
cout << "lval\n";
}
MyException(std::exception &&exc) : std::exception(std::forward<std::exception>(exc))
{
cout << "rval\n";
}
};
...
...
try
{
throw std::exception("Oh no!");
// above is rvalue since it's got no name, what if the throw is made as
// std::exception lvalExc("Oh wierd!");
// throw lvalExc;
// if the throw is made thus, how can it be caught by catch(std::exception &&exc)?
}
catch(std::exception &&rValRef)
{
cout << "rValRef!\n";
throw MyException(std::forward<std::exception>(rValRef));
}
Когато се опитах да хвана по стойност или по (const) lvalue ref. компилаторът казва, че тези случаи вече се обработват от клаузата rvalue ref catch
, което е разбираемо, тъй като изключение е xvalue и може би най-добрият начин за улавяне на xvalue е rvalue ref (поправете ме, ако греша). Но може ли някой да обясни за перфектното препращане в горния случай на създаване на изключение? Правилно ли е? Въпреки че се компилира, има ли смисъл или полезно? Трябва ли C++ библиотеката, която използвам, да има внедрен конструктор за преместване за нейния std::exception
, за да бъде този вид употреба наистина смислена? Опитах се да търся статии и SO въпроси за препратки към rvalue по отношение на изключения, не можах да намеря такива.