Date: Fri, 12 Dec 2025 18:11:35 +0800
Consider this 2 exception outputs.
===== case A =====
terminate called after throwing an instance of 'network_error'
what(): connection failed (104).
===== case B =====
terminate called after throwing an instance of 'network_error'
what(): conection failed (with layer = transport, protocol = tcp,
local_endpoint = 0.0.0.0:21798, remote_endpoint = 198.23.64.125:37720,
error_code = 104, reason = "Connection reset by peer", status = "SYN ACK")
In user's perspective, the user/caller usually prefers an output like B.
But currently almost all C++ 3rd-party libraries (who use exception rather
then error_code/assert) provides something like A.
Maybe should we **encourage** people to carry more information in
exceptions?
On Fri, Dec 12, 2025 at 4:28 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>
> On Fri, 12 Dec 2025, 03:46 叶易安 via Std-Proposals, <
> std-proposals_at_[hidden]> wrote:
>
>> Most times we would like to know as more message as possible when an
>> error occurs, such as:
>> 1. which argument is invalid
>> 2. stacktrace [available by
>> std::set_terminate(std::stacktrace::current()...)]
>>
>> Currently the message in [1.] is always useless.
>>
>
> Is it though?
>
> For example:
>> (clang22): "libc++abi: terminating due to uncaught exception of type
>> std::out_of_range: vector"
>>
>> Gcc15 saw this problem, and has internally changed the
>> `std::vector::at()` implementation by calling a new
>> `__throw_out_of_range_fmt`. Now gcc can provide a much helpful output:
>> (gcc15): "what(): vector::_M_range_check: __n (which is 42) >=
>> this->size() (which is 24)"
>>
>
> So not always useless then. It's a problem of the code throwing the
> exception.
>
>
>> Can we add a new overload constructor to make the exceptions-formatting
>> in a standard way?
>> =====
>> /*new overload*/
>> throw std::out_of_range("index {} is out of range with size {}", pos,
>> this->size());
>>
>> /*currently available, but verbose | tedious! */
>> throw std::out_of_range(std::format("index {} is out of range with size
>> {}", pos, this->size()));
>>
>
> I'm not convinced by the motivation. Throwing exceptions isn't something
> that's so common that we need to save 13 characters here. The std::format
> solution seems fine.
>
> Note that the libstdc++ helper function doesn't rely on any new
> constructor, it just formats a string and passes that to the existing
> constructor. You can write your own helper functions to do that too.
>
>
>
>> /*add a new overload*/
>> std::logic_error::logic_error(std::format_string<Ts...>, Ts&&...)
>>
>
> And every other exception type in <stdexcept>?
>
>
> =====
>>
>> And:
>> 1. This will not break ABI.
>> 2. We **encourage** users to carry essential information, rather than a
>> plain text.
>>
>
> It's already possible today though.
>
>>
===== case A =====
terminate called after throwing an instance of 'network_error'
what(): connection failed (104).
===== case B =====
terminate called after throwing an instance of 'network_error'
what(): conection failed (with layer = transport, protocol = tcp,
local_endpoint = 0.0.0.0:21798, remote_endpoint = 198.23.64.125:37720,
error_code = 104, reason = "Connection reset by peer", status = "SYN ACK")
In user's perspective, the user/caller usually prefers an output like B.
But currently almost all C++ 3rd-party libraries (who use exception rather
then error_code/assert) provides something like A.
Maybe should we **encourage** people to carry more information in
exceptions?
On Fri, Dec 12, 2025 at 4:28 PM Jonathan Wakely <cxx_at_[hidden]> wrote:
>
>
> On Fri, 12 Dec 2025, 03:46 叶易安 via Std-Proposals, <
> std-proposals_at_[hidden]> wrote:
>
>> Most times we would like to know as more message as possible when an
>> error occurs, such as:
>> 1. which argument is invalid
>> 2. stacktrace [available by
>> std::set_terminate(std::stacktrace::current()...)]
>>
>> Currently the message in [1.] is always useless.
>>
>
> Is it though?
>
> For example:
>> (clang22): "libc++abi: terminating due to uncaught exception of type
>> std::out_of_range: vector"
>>
>> Gcc15 saw this problem, and has internally changed the
>> `std::vector::at()` implementation by calling a new
>> `__throw_out_of_range_fmt`. Now gcc can provide a much helpful output:
>> (gcc15): "what(): vector::_M_range_check: __n (which is 42) >=
>> this->size() (which is 24)"
>>
>
> So not always useless then. It's a problem of the code throwing the
> exception.
>
>
>> Can we add a new overload constructor to make the exceptions-formatting
>> in a standard way?
>> =====
>> /*new overload*/
>> throw std::out_of_range("index {} is out of range with size {}", pos,
>> this->size());
>>
>> /*currently available, but verbose | tedious! */
>> throw std::out_of_range(std::format("index {} is out of range with size
>> {}", pos, this->size()));
>>
>
> I'm not convinced by the motivation. Throwing exceptions isn't something
> that's so common that we need to save 13 characters here. The std::format
> solution seems fine.
>
> Note that the libstdc++ helper function doesn't rely on any new
> constructor, it just formats a string and passes that to the existing
> constructor. You can write your own helper functions to do that too.
>
>
>
>> /*add a new overload*/
>> std::logic_error::logic_error(std::format_string<Ts...>, Ts&&...)
>>
>
> And every other exception type in <stdexcept>?
>
>
> =====
>>
>> And:
>> 1. This will not break ABI.
>> 2. We **encourage** users to carry essential information, rather than a
>> plain text.
>>
>
> It's already possible today though.
>
>>
Received on 2025-12-12 10:11:53
