ned14 / status-code

Proposed SG14 status_code for the C++ standard

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

First class `<format>`/fmtlib support

BurningEnlightenment opened this issue · comments

Problem Description

Since <iostream> has been superseeded in C++20/23 as the preferred stringification/formatting API, I would like to use either fmtlib or std::format to format error messages/log output. This is currently possible, but looks like this:

SYSTEM_ERROR2_NAMESPACE::system_code code = /*...*/;
std::print("xx API returned [{}|{}]", code.domain().name().c_str(), code.message().c_str());

And the above might still be problematic as it looses the exact error code value and the domain Id.

Proposed Solution

Add a format_support.hpp header similar to the existing iostream_support.hpp which provides the respective formatter specializations for the following types after detecting the presence of C++20 <format> and fmtlib:

  • status_code_domain::string_ref (can be delegated to (std|fmt)::formatter<string_view>)
  • status_code_domain
  • generic_code and its errored_status_code variant
  • status_code<detail::erased<ErasedType>> and errored_status_code<detail::erased<ErasedType>>
  • the native system codes e.g. POSIX, NT, etc.

The formatter domain/code specializations should support a formatting spec for specifying if textual or raw representations should be used. The status_code formatters should support a "full" output mode i.e. something like domain name + message.

Possible Alternative Approaches

Of course these specializations could be provided by downstream users. However, this doesn't compose well in case of diamond-shaped dependency DAGs.

Additional Context

I have implemented barebones formatter specializations for some of these types but without alternate formatting modes.

You've got some good timing on this.

In the Issaquah meeting, LEWG asked for proposed wording for this library. I am very slowly writing that.

One of the things suggested was that the quick status code from enum facility ought to be able to supply a formatter template from which textual messages could be more intelligently generated. Obviously if we were to implement that, it would need some sort of support in the main status code classes. A big constraint is that we somehow need to avoid format being mandatory in the ABI, as I'm not sure if format can be or will be Freestanding.

What I was roughly thinking of was that if a string contained format expansion points with named identifiers where those names were domain_name, status_code_value etc then we would automagically expand those. Something to be remembered is that new logging token passthrough facility they added to format for C++ 23, whatever we do may need to be compatible with that.

You can have a crack at that if you want? Note you probably ought to be using std format rather than Victor's, the only shipping implementation is MSVCs right now. I vaguely remember Mr. Wakely is nearly done with libstdc++'s?

Also, yeah bump CI runners to 22.04 LTS. Thanks!

Something to be remembered is that new logging token passthrough facility they added to format for C++ 23

Could you point me to the paper or standards section? I have no idea what you are referring to 😅

One of the things suggested was that the quick status code from enum facility ought to be able to supply a formatter template from which textual messages could be more intelligently generated. Obviously if we were to implement that, it would need some sort of support in the main status code classes.

Just to rule out misunderstandings: This would be a way to influence the _quick_status_code_from_enum_domain::message() implementation by interpreting the quick_status_code_from_enum_defaults::mapping::message field. I like that idea. However, this would be orthogonal to what I initially had in mind:

SYSTEM_ERROR2_NAMESPACE::generic_code code = SYSTEM_ERROR2_NAMESPACE::errc::bad_message;
BOOST_TEST(std::format("xx API returned {}", code) == "xx API returned (generic domain, Bad message)"s); 
BOOST_TEST(std::format("xx API returned {:#}", code) == "xx API returned (0x746d6354f4f733e9, 0x68)"s); 
BOOST_TEST(std::format("xx API returned {:(d|v)}", code) == "xx API returned (generic domain|0x68)"s); 

Do you want this to work, too? (I haven't put any thought into the format specification language).

Note you probably ought to be using std format rather than Victor's

I think we can support both with a single implementation via some templating as their APIs are similar enough. This certainly would be beneficial for people on C++14/C++17 or those using advanced non-standard features like dynamic_format_arg_store.

quick status code from enum facility

Two things that bothered me a bit:

  1. It has "blessed" implicit status_code constructors. It feels like there ought to be a general customization point here. Specifically it prevents users from writing their own facility which can exploit their error coding structure (no/single success code, vastly simpler generic_code equivalence, etc.).
  2. The name feels verbose? awkward? I'd propose something like data_defined_status_code (I know, I know, it's bikeshedding).

Could you point me to the paper or standards section? I have no idea what you are referring to

It's the new {:?} facility. Somebody has very kindly already written it up into https://en.cppreference.com/w/cpp/utility/format/formatter#Formatting_escaped_characters_and_strings_.28since_C.2B.2B23.29

Just to rule out misunderstandings: This would be a way to influence the _quick_status_code_from_enum_domain::message() implementation by interpreting the quick_status_code_from_enum_defaults::mapping::message field. I like that idea. However, this would be orthogonal to what I initially had in mind:

Sure, and I haven't given it much thought myself either. What I ought to go do is summarise all uses of status code in the work codebase, and see all the locations where devs customised the message, and from that derive what needs to be done.

That doesn't change the direct format support of course. Your suggested formatter syntax seems a reasonable first start.

BTW how do you fancy writing a WG21 paper? Now that P1028 is into wording, significant changes to P1028 must take the form of a new WG21 paper. It would do no harm for your CV. If you were to implement formatting for status codes, it might be an idea to run your proposed changes via WG21, so you get experience with the process and that's a great talking point for job interviews etc later. As much as WG21 process is derided, most large orgs have very similar processes and employers like to see candidates who have gone through that mill at least once. If you're heading into academia, the WG21 process is very much like a PhD oral defence spread out over multiple rounds. You present, people in the room interrogate and attack your proposal (and sometimes you), you defend, next round. It's not especially pleasant, but it is good for you.

Also, if you get a paper in, you can ask for financial support to attend a meeting, then we can meet in person :)

Next meeting is in Varna, Bulgaria if that's of any use. You may wish your paper to appear in the Kona meeting for obvious reasons, I suspect I won't be at that one. The meeting thereafter is Tokyo, I'm currently unsure about that one.

Two things that bothered me a bit:

It has "blessed" implicit status_code constructors. It feels like there ought to be a general customization point here. Specifically it prevents users from writing their own facility which can exploit their error coding structure (no/single success code, vastly simpler generic_code equivalence, etc.).

The code base definitely could become more complex, or it could drop C++ 11 support. I wanted to keep this specific reference implementation simple, as WG21 folk already have had issue wrapping their heads around it.

Incidentally WG21 want large swathes of the proposed API to be implementation defined, so for example all the string ref stuff is implementation defined and I think we may even be marking the virtual functions in the domain implementation as implementation defined.

The name feels verbose? awkward? I'd propose something like data_defined_status_code (I know, I know, it's bikeshedding).

Everybody hates the name. Bikeshedding of better naming produced no obviously better names. Almost certainly they'll make me go canvas the C++ community for better names and come back to them with a list to scope down yet more bikeshedding, but we're not there yet.

So wrt WG21 participation: Yes, I'd be willling to write a paper. I've watched WG21 proceedings with interest for a while now and read a bit about the procedures of the committee in the past, so it's not completely unfamiliar. Are there useful resources beyond https://isocpp.org/std/submit-a-proposal that I should be aware of?

Furthermore I have informally approached my employer about a possible ISO membership, and they have expressed cautious interest so far. So I need way more details about the whole ordeal before I can properly pitch this to them. Can you provide me with some information about joining a national body/point me in the right direction? Anyways, I guess that is too short notice for the next/Varna meeting, so I would probably need to attend there as a guest. Does this make sense?

Are there useful resources beyond https://isocpp.org/std/submit-a-proposal that I should be aware of?

Only don't overthink it or get overly stressed about it. If you feel up to it, proposing wording would be super great, but I know that's a big ask.

Furthermore I have informally approached my employer about a possible ISO membership, and they have expressed cautious interest so far. So I need way more details about the whole ordeal before I can properly pitch this to them. Can you provide me with some information about joining a national body/point me in the right direction? Anyways, I guess that is too short notice for the next/Varna meeting, so I would probably need to attend there as a guest. Does this make sense?

You'd be German national body?

If so, Nico is the man you need to talk to. I see no reason you can't be inducted well before Varna. Nico runs an efficient NB.

Once you're in and have your paper submitted, you can ask the Standard C++ Foundation for financial help for attending, if your employer is unwilling to pay for it and the German NB doesn't have its own process. Nico can advise.

You can find Nico at https://josuttis.de/

Many thanks!