Date: Tue, 10 Jan 2023 10:22:32 +0000
On Tue, Jan 10, 2023 at 12:23 AM Thiago Macieira via Std-Proposals wrote:
> > Choice 1: Deprecate the throwing of non-std::exception's.
> > Choice 2: Provide RTTI inside catch(...)
>
> Choice 3: do neither.
>
> As I said, throwing types not derived from std::exception should be
> discouraged by recommendation. The language doesn't need to enforce that
> because the *Core* language doesn't need to know anything about
> std::exception. It's just a polymorphic type like any other, to which the
> Standard *Library* assigns special meaning and we all by convention agree to
> it.
There is no distinction anymore between the core language and the
classes defined
in the standard library. I mean one of the operators in the core
language requires
a header file (i.e. typeid). And not to mention the many classes in
the standard library
that cannot be written in C++ (for example std::has_virtual_destructor).
> Realistically, the only things that will hit a catch (...) and not a
> catch (std::exception &) are foreign exceptions. There won't be a typeinfo for
> them in the first place.
>
> The proposal needs to deal with that non-hypothetical.
So maybe we need to start talking about how C++26 deals with foreign exceptions?
I see that you already broached this topic 6 years ago on the
std-discussion group:
https://groups.google.com/a/isocpp.org/g/std-discussion/c/DLQY1iYoe_w
Perhaps we should standardise the catching of a foreign exception:
catch ( std::alien_exception const & )
{
}
and maybe even go a step further to provide compatibility with a handful
of other languages, something like what I've done on GodBolt here:
https://godbolt.org/z/Ea49PrPWo
And here's all the code copy-pasted from GodBolt:
namespace std {
struct alien_exception /* does not inherit from exception */ {
enum class language : unsigned int { java=1u, csharp, python };
virtual language lang(void) const noexcept = 0;
virtual char const *what(void) const noexcept = 0;
};
namespace aliens {
namespace java {
struct exception : alien_exception {
char const *getLocalizedMessage(void) const noexcept;
char const *getMessage(void) const noexcept;
std::stacktrace getStackTrace(void) const noexcept;
char const *what(void) const noexcept override { return
this->getMessage(); }
language lang(void) const noexcept override { return language::java; }
};
}
namespace python {
struct exception : alien_exception {
char const *const *notes(void) const noexcept; /* null terminated */
std::stacktrace traceback() const noexcept;
char const *what(void) const noexcept override { return
this->notes()[0u]; }
language lang(void) const noexcept override { return language::python; }
};
}
namespace python {
struct BaseException : exception {};
struct BaseExceptionGroup : BaseException {};
struct GeneratorExit : BaseException {};
struct KeyboardInterrupt : BaseException {};
struct SystemExit : BaseException {};
struct Exception : BaseException {};
struct ArithmeticError : Exception {};
struct FloatingPointError : ArithmeticError {};
struct OverflowError : ArithmeticError {};
struct ZeroDivisionError : ArithmeticError {};
struct AssertionError : Exception {};
struct AttributeError : Exception {};
struct BufferError : Exception {};
struct EOFError : Exception {};
struct ExceptionGroupBaseExceptionGroup : Exception {};
struct ImportError : Exception {};
struct ModuleNotFoundError : ImportError {};
struct LookupError : Exception {};
struct IndexError : LookupError {};
struct KeyError : LookupError {};
struct MemoryError : Exception {};
struct NameError : Exception {};
struct UnboundLocalError : NameError {};
struct OSError : Exception {};
struct BlockingIOError : OSError {};
struct ChildProcessError : OSError {};
struct ConnectionError : OSError {};
struct BrokenPipeError : ConnectionError {};
struct ConnectionAbortedError : ConnectionError {};
struct ConnectionRefusedError : ConnectionError {};
struct ConnectionResetError : ConnectionError {};
struct FileExistsError : OSError {};
struct FileNotFoundError : OSError {};
struct InterruptedError : OSError {};
struct IsADirectoryError : OSError {};
struct NotADirectoryError : OSError {};
struct PermissionError : OSError {};
struct ProcessLookupError : OSError {};
struct TimeoutError : OSError {};
struct ReferenceError : Exception {};
struct RuntimeError : Exception {};
struct NotImplementedError : RuntimeError {};
struct RecursionError : RuntimeError {};
struct StopAsyncIteration : Exception {};
struct StopIteration : Exception {};
struct SyntaxError : Exception {};
struct IndentationError : SyntaxError {};
struct TabError : IndentationError {};
struct SystemError : Exception {};
struct TypeError : Exception {};
struct ValueError : Exception {};
struct UnicodeError : ValueError {};
struct UnicodeDecodeError : UnicodeError {};
struct UnicodeEncodeError : UnicodeError {};
struct UnicodeTranslateError : UnicodeError {};
struct Warning : Exception {};
struct BytesWarning : Warning {};
struct DeprecationWarning : Warning {};
struct EncodingWarning : Warning {};
struct FutureWarning : Warning {};
struct ImportWarning : Warning {};
struct PendingDeprecationWarning : Warning {};
struct ResourceWarning : Warning {};
struct RuntimeWarning : Warning {};
struct SyntaxWarning : Warning {};
struct UnicodeWarning : Warning {};
struct UserWarning : Warning {};
} // close namespace 'python'
} // close namespace 'aliens'
class forced_stack_unwind {};
} // close namespace 'std'
extern int Some_Func_In_Python_Library(void) { return 7; /* or throws
a Java exception */ }
int main(void)
{
try { Some_Func_In_Python_Library(); }
catch ( std::aliens::python::FloatingPointError const & )
{
// The specific Python exception we want to handle
}
catch ( std::aliens::python::exception const & )
{
// Any exception thrown from Python
}
catch ( std::alien_exception const &)
{
// Maybe the Python library linked with an
// Eiffel library that threw an exception
}
catch ( std::forced_stack_unwind )
{
}
}
> > Choice 1: Deprecate the throwing of non-std::exception's.
> > Choice 2: Provide RTTI inside catch(...)
>
> Choice 3: do neither.
>
> As I said, throwing types not derived from std::exception should be
> discouraged by recommendation. The language doesn't need to enforce that
> because the *Core* language doesn't need to know anything about
> std::exception. It's just a polymorphic type like any other, to which the
> Standard *Library* assigns special meaning and we all by convention agree to
> it.
There is no distinction anymore between the core language and the
classes defined
in the standard library. I mean one of the operators in the core
language requires
a header file (i.e. typeid). And not to mention the many classes in
the standard library
that cannot be written in C++ (for example std::has_virtual_destructor).
> Realistically, the only things that will hit a catch (...) and not a
> catch (std::exception &) are foreign exceptions. There won't be a typeinfo for
> them in the first place.
>
> The proposal needs to deal with that non-hypothetical.
So maybe we need to start talking about how C++26 deals with foreign exceptions?
I see that you already broached this topic 6 years ago on the
std-discussion group:
https://groups.google.com/a/isocpp.org/g/std-discussion/c/DLQY1iYoe_w
Perhaps we should standardise the catching of a foreign exception:
catch ( std::alien_exception const & )
{
}
and maybe even go a step further to provide compatibility with a handful
of other languages, something like what I've done on GodBolt here:
https://godbolt.org/z/Ea49PrPWo
And here's all the code copy-pasted from GodBolt:
namespace std {
struct alien_exception /* does not inherit from exception */ {
enum class language : unsigned int { java=1u, csharp, python };
virtual language lang(void) const noexcept = 0;
virtual char const *what(void) const noexcept = 0;
};
namespace aliens {
namespace java {
struct exception : alien_exception {
char const *getLocalizedMessage(void) const noexcept;
char const *getMessage(void) const noexcept;
std::stacktrace getStackTrace(void) const noexcept;
char const *what(void) const noexcept override { return
this->getMessage(); }
language lang(void) const noexcept override { return language::java; }
};
}
namespace python {
struct exception : alien_exception {
char const *const *notes(void) const noexcept; /* null terminated */
std::stacktrace traceback() const noexcept;
char const *what(void) const noexcept override { return
this->notes()[0u]; }
language lang(void) const noexcept override { return language::python; }
};
}
namespace python {
struct BaseException : exception {};
struct BaseExceptionGroup : BaseException {};
struct GeneratorExit : BaseException {};
struct KeyboardInterrupt : BaseException {};
struct SystemExit : BaseException {};
struct Exception : BaseException {};
struct ArithmeticError : Exception {};
struct FloatingPointError : ArithmeticError {};
struct OverflowError : ArithmeticError {};
struct ZeroDivisionError : ArithmeticError {};
struct AssertionError : Exception {};
struct AttributeError : Exception {};
struct BufferError : Exception {};
struct EOFError : Exception {};
struct ExceptionGroupBaseExceptionGroup : Exception {};
struct ImportError : Exception {};
struct ModuleNotFoundError : ImportError {};
struct LookupError : Exception {};
struct IndexError : LookupError {};
struct KeyError : LookupError {};
struct MemoryError : Exception {};
struct NameError : Exception {};
struct UnboundLocalError : NameError {};
struct OSError : Exception {};
struct BlockingIOError : OSError {};
struct ChildProcessError : OSError {};
struct ConnectionError : OSError {};
struct BrokenPipeError : ConnectionError {};
struct ConnectionAbortedError : ConnectionError {};
struct ConnectionRefusedError : ConnectionError {};
struct ConnectionResetError : ConnectionError {};
struct FileExistsError : OSError {};
struct FileNotFoundError : OSError {};
struct InterruptedError : OSError {};
struct IsADirectoryError : OSError {};
struct NotADirectoryError : OSError {};
struct PermissionError : OSError {};
struct ProcessLookupError : OSError {};
struct TimeoutError : OSError {};
struct ReferenceError : Exception {};
struct RuntimeError : Exception {};
struct NotImplementedError : RuntimeError {};
struct RecursionError : RuntimeError {};
struct StopAsyncIteration : Exception {};
struct StopIteration : Exception {};
struct SyntaxError : Exception {};
struct IndentationError : SyntaxError {};
struct TabError : IndentationError {};
struct SystemError : Exception {};
struct TypeError : Exception {};
struct ValueError : Exception {};
struct UnicodeError : ValueError {};
struct UnicodeDecodeError : UnicodeError {};
struct UnicodeEncodeError : UnicodeError {};
struct UnicodeTranslateError : UnicodeError {};
struct Warning : Exception {};
struct BytesWarning : Warning {};
struct DeprecationWarning : Warning {};
struct EncodingWarning : Warning {};
struct FutureWarning : Warning {};
struct ImportWarning : Warning {};
struct PendingDeprecationWarning : Warning {};
struct ResourceWarning : Warning {};
struct RuntimeWarning : Warning {};
struct SyntaxWarning : Warning {};
struct UnicodeWarning : Warning {};
struct UserWarning : Warning {};
} // close namespace 'python'
} // close namespace 'aliens'
class forced_stack_unwind {};
} // close namespace 'std'
extern int Some_Func_In_Python_Library(void) { return 7; /* or throws
a Java exception */ }
int main(void)
{
try { Some_Func_In_Python_Library(); }
catch ( std::aliens::python::FloatingPointError const & )
{
// The specific Python exception we want to handle
}
catch ( std::aliens::python::exception const & )
{
// Any exception thrown from Python
}
catch ( std::alien_exception const &)
{
// Maybe the Python library linked with an
// Eiffel library that threw an exception
}
catch ( std::forced_stack_unwind )
{
}
}
Received on 2023-01-10 10:22:43