[system] - creation of system_error

Hello, creating a system_error requires : sys::error_code e( errno, sys::from_errno); std::string msg; sys::system_message( e, msg); sys::system_error( msg, e); I would find it easier if I had only to type: sys::error_code e( errno, sys::from_errno); sys::system_error( e); // what() == system_message regards, Oliver

Oliver.Kowalke@qimonda.com wrote:
I agree. system_error::system_error should have its arguments reversed and what_arg should be optional. The postcondition of what() indicates that this might have been the intent all along. In addition, I think that the setters in error_code need to be dropped. In the rare situations where an error_code is already available and needs to be repurposed (a questionable activity as its original contents would be lost), instead of: e.sysno_value( sv ); one would use: e = error_code( sv ); The postconditions of the constructors need to be changed to: sysno_value() == err && errno_value() == to_errno( err ); and errno_value() == err && sysno_value() == to_sysno( err ); respectively. sysno_value() and errno_value() now would need no further (normative) explanations. The postcondition of error() is ill-formed as currently given and -- in case error() is provided at all (questionable) -- needs to be just errno_value() == 0. The current intrerface gives priority to system error codes as evidenced by the single argument constructor. I could argue that we need to reverse that and give priority to errno, but another approach would be to just give the two equal standing with a from_sysno enum. This would help code reviewers as in: sys::error_code e( r, sys::from_sysno ); it is now explicit that r is supposed to hold a system error code. It isn't clear why there is no error_code::message() const. Probably to not introduce a dependency on std::string and to avoid a copy. In my opinion, if you have to convert error codes to strings in an inner loop where the copy might be of any significance, you have already lost. :-) So I'd prefer the user-friendlier approach of std::string error_code::message() const; std::wstring error_code::wmessage() const; as people generally prefer members. The introduction of operator== is also of questionable utility as it also forces us to prefer one of the two codes over the other. If I want to compare the system error codes, let me do so explicitly: e1.sysno_value() == e2.sysno_value() This also helps code reviewers. Having an operator== for which e1 == e2 doesn't necessarily imply that e1 and e2 are equivalent would need much explanation.

Hi Peter, Peter Dimov <pdimov@mmltd.net> wrote:
I would prefer that they are given equal weight, but as I've said elsewhere I also believe there's a need for other error categories.
IMHO the error_code class should have fewer member functions, not more, and it should look more like a class that emulates a builtin type. However this line of thinking is probably driven by how I see this class being used wrt asio. Here's another thought: since POSIX strerror is defined to return a locale-dependent string, perhaps a C++ equivalent ought to use std::locale? (However, in practice this needs to be implemented on top of available system APIs, and I don't know if it's possible to implement std::locale-based functions in terms of setlocale().)
If the constructors give equal weight to error types, then this would not be a problem. I think operator== and != are necessary because I would like to be able to define global error objects for the "well known" errors that can be returned by socket operations. E.g.: namespace boost { namespace asio { namespace error { extern const error_code eof; extern const error_code network_reset; extern const error_code operation_aborted; ... }}} These values would just be compared against the result of operations, as in: void handle_read(error_code ec) { if (ec == boost::asio::error::operation_aborted) ... } Whether the underlying error is an errno or a sysno isn't relevant to these use cases. Cheers, Chris

Christopher Kohlhoff wrote:
As long as there is at least one member, it's no longer a built-in-like. :-)
I think that messages are fine as-is. Their primary audience is people who don't care about languages and locales (the same audience that finds what() useful). Programmers who do care will create their own mapping tables based on errno (or sysno, if they don't need portability for the error message module).
It is. The problem is that in general, there is no 1:1 mapping between sysno and errno. This means that in principle you can have error_codes e1, e2 and e3 such that e1.errno_value() == e2.errno_value() && e1.sysno_value() != e2.sysno_value() and e1.errno_value() != e3.errno_value() && e1.sysno_value() == e3.sysno_value() so the current operator== does not imply equivalence.
Under implementation A, you'll get sysno's from the underlying low level module, and the current operator== will do what you want. But under implementation B you may get errno from the low level module (even though the OS may have another sysno) and if two errno's map to the same sysno, there is a problem. It may not be a practical problem, of course. An operator== that compares both sysno_vaue() and errno_value() would allow the above to work reliably, though... as long as there is a single sysno in the OS, as you pointed out. :-)

Peter Dimov <pdimov@mmltd.net> wrote:
Elsewhere I suggested that errno_value() and sysno_value() getters could be replaced by overloads of the free functions to_errno and to_sysno. If the setters are also removed as suggested in this thread, then that leaves a grand total of 0 named member functions :)
I'm not particularly fussed, but if we implement in terms of strerror (or strerror_r) on POSIX platforms then we are already getting locale support, but it's the C locale which determines the error message.
Yes, this does makes me think that it might be better if an error_code only had one true value, and that value is represented by whatever category and error number it is created with. It would only compare as equal to another error_code that was created with exactly the same category and error number. Conversion between errors in different categories should then be explicit (using to_errno or to_sysno, say). I don't know what implications this would have on the use of error_code in the filesystem library, however. Cheers, Chris

Peter Dimov <pdimov@mmltd.net> wrote:
I think this is a good argument for naming the accessor functions (whether they are member functions or not) to clearly indicate that they perform lossy conversions. To me, the names sysno_value() and errno_value() don't convey this -- they sound like they are simple accessors for data members (until one consults the documentation). And as Peter demonstrates above, one might reasonably expect that comparing all exposed data members would give the same result as operator==. But, if the names were something like to_sysno/to_errno or as_sysno/as_errno, the above expression would become: e1.to_sysno() == e2.to_sysno() && e1.to_errno() == e2.to_errno() && e1 != e2 and I no longer think it looks surprising. Cheers, Chris

Christopher Kohlhoff wrote:
I suggest following names: errno_from(ec); sysno_from(ec); 1) it is longer, but better reflects what is going on. 2) it is consistent with string_from() function I'm working on. One more idea about message() function - it can be replaced with the above mentioned string_from/wstring_from function. All what should be done - an '<<' operator should be provided. Best, Oleg Abrosimov.
participants (4)
-
Christopher Kohlhoff
-
Oleg Abrosimov
-
Oliver.Kowalke@qimonda.com
-
Peter Dimov