Doc. no. WG21/N2066=06-0136
Date:
2006-09-07
Project: Programming Language C++
Reply to: Beman Dawes <bdawes@acm.org>
N1975 Filesystem Library Proposal for TR2, accepted for Library Technical Report 2 (TR2) at the Berlin meeting, included additional components to supplement the Standard Library's Diagnostics clause. Since then, these error reporting components have received wider public scrutiny and enhancements have been made to the design. The enhanced version has been used by N2054, Networking Library Proposal for TR2, demonstrating that these error reporting components are in fact useful beyond of the original Filesystem Library.
The enhancements fall into two areas:
The original proposal viewed error categories as a binary choice between
errno
(i.e. POSIX-style) and the native operating system's error
codes. The enhancements proposed here allow as many additional error categories
as are needed by either implementations or by users. The need to support
additional error categories, for example, occurs in some networking library
implementations because they are built on top of the POSIX getaddrinfo
API that uses error codes
not based on errno
.
Christopher Kohlhoff and Peter Dimov made important contributions to the design. Comments and suggestions were also received from Pavel Vozenilek, Gennaro Prota, Dave Abrahams, Jeff Garland, Iain Hanson, Oliver Kowalke, and Oleg Abrosimov. Christopher Kohlhoff suggested several improvements in the current paper.
Replace the text of the TR2 Diagnostics library with:
This clause describes components that C++ programs may use to detect and report error conditions that have an associated error code.
<error_code
>namespace std { namespace tr2 { namespace sys { class error_category; class error_code; class system_error; typedef int (*errno_decoder)(const error_code &); typedef string (*message_decoder)(const error_code &); typedef wstring (*wmessage_decoder)(const error_code &);
const error_category errno_ecat(unspecified-value); const error_category native_ecat(unspecified-value); // possibly same value as errno_ecat size_t hash_value(const error_code & ec); } // namespace sys } // namespace tr2 } // namespace std
size_t hash_value( const error_code & ec );
Returns: A hash value representing
ec
.
error_category
The class error_category
defines the type of objects used to identify the source and encoding of a particular
category of error codes.
namespace std { namespace tr2 { namespace sys { class error_category { public: typedef uint_least32_t value_type; error_category(); explicit error_category( value_type v ); const value_type value() const; void assign( value_type v ); bool operator==( const error_category & rhs ) const; bool operator!=( const error_category & rhs ) const; bool operator< ( const error_category & rhs ) const; bool operator<=( const error_category & rhs ) const; bool operator> ( const error_category & rhs ) const; bool operator>=( const error_category & rhs ) const; }; } // namespace sys } // namespace tr2 } // namespace std
error_category
memberserror_category();
Effects: Constructs an object of type
error_category
.Postconditions:
value() == errno_ecat
.
explicit error_category(value_type v);
Effects: Constructs an object of type
error_category
.Postconditions:
value() == v
.
const value_type value() const;
Returns: The value specified by postconditions of the most recent
assign
, if any, or of the constructor.
void assign(value_type v);
Postconditions:
value() == v
.
bool operator==(const error_category & rhs) const;
Returns:
value() == rhs.value()
.
bool operator!=(const error_category & rhs) const;
Returns:
value() != rhs.value()
.
bool operator< (const error_category & rhs) const;
Returns:
value() < rhs.value()
.
bool operator<=(const error_category & rhs) const;
Returns:
value() <= rhs.value()
.
bool operator> (const error_category & rhs) const;
Returns:
value() > rhs.value()
.
bool operator>=(const error_category & rhs) const;
Returns:
value() >= rhs.value()
.
error_code
The class error_code
defines the type of objects used to
identify errors that have an associated error code value, such as those originating from
the operating system.
namespace std { namespace tr2 { namespace sys { class error_code { public: typedef int_least32_t value_type; // constructors and assignment: error_code(); error_code(value_type val, error_category cat); void assign(value_type val, error_category cat); // observers: value_type value() const; error_category category() const; int to_errno() const; string message() const; wstring wmessage() const; operator unspecified-bool-type() const; bool operator!() const; // relationals: bool operator==(const error_code & rhs) const; bool operator!=(const error_code & rhs) const; bool operator< (const error_code & rhs) const; bool operator<=(const error_code & rhs) const; bool operator> (const error_code & rhs) const; bool operator>=(const error_code & rhs) const; // statics: static error_category new_category(errno_decoder ed=0, message_decoder md=0, wmessage_decoder wmd=0); static bool get_decoders(error_category cat, errno_decoder & ed, message_decoder & md, wmessage_decoder & wmd); }; } // namespace sys } // namespace tr2 } // namespace std
error_code
memberserror_code();
Effects: Constructs an object of type
error_code
.Postconditions:
value() == 0 && category() == errno_ecat
.
error_code(value_type val, error_category cat);
Effects: Constructs an object of type
error_code
.Postconditions:
value() == val && category() == cat
.
void assign(value_type val, error_category cat);
Postconditions:
value() == val && category() == cat
.
value_type value() const;
Returns:
value()
as specified by postconditions of the most recentassign
, if any, or of the constructor.
error_category category() const;
Returns:
category()
as specified by postconditions of the most recentassign
, if any, or of the constructor.
int to_errno() const;
Effects:
errno_decoder ed;
message_decoder md;
wmessage_decoder wmd;
bool ok( get_decoders( category(), ed, md, wmd ) );Returns: If
ok && ed
,ed(*this)
, otherwiseEOTHER
.[Note: The intent is to return the ISO/IEC 9945:2003, Portable Operating System Interface (POSIX) error number that the implementation determines most closely corresponds to
value()
. --end note.]
string message() const;
wstring wmessage() const;
Effects:
errno_decoder ed;
message_decoder md;
wmessage_decoder wmd;
bool ok( get_decoders( category(), ed, md, wmd ) );Returns:
message(): Ifok && md
,md(*this)
, otherwisestring()
.
wmessage(): Ifok && wmd
,wmd(*this)
, otherwisewstring()
.Remarks: If
category() == errno_ec
, the string is as returned bystrerror()
. Otherwise, the method used by the implementation to determine the string is unspecified.[Note: The intent is to return a locale sensitive string that describes the error corresponding to
value()
. --end note.]
operator unspecified-bool-type() const;
Returns: if
value() != value_type()
, returns a value that will evaluatetrue
in a boolean context; otherwise, returns a value that will evaluatefalse
in a boolean context. The value type returned shall not be convertible toint
.Throws: nothing.
[ Note: This conversion can be used in contexts where a
bool
is expected (e.g., anif
condition); however, implicit conversions (e.g., toint
) that can occur withbool
are not allowed, eliminating some sources of user error. One possible implementation choice for this type is pointer-to-member. —end note ]
bool operator!() const;
Returns:
value() == value_type()
.
bool operator==(const error_code & rhs) const;
Returns:
value() == rhs.value() && category() == rhs.category()
.
bool operator!=(const error_code & rhs) const;
Returns:
!(*this == rhs)
.
bool operator< (const error_code & rhs) const;
Returns:
category()<rhs.category() || (category()==rhs.category() && value()<rhs.value())
.
bool operator<=(const error_code & rhs) const;
Returns:
!(*this > rhs)
.
bool operator> (const error_code & rhs) const;
Returns:
category()>rhs.category() || (category()==rhs.category() && value()>rhs.value())
.
bool operator>=(const error_code & rhs) const;
Returns:
!(*this < rhs)
.
static error_category new_category(errno_decoder ed=0, message_decoder md=0, wmessage_decoder wmd=0 );
Effects: Constructs a new
error_category
object.Creates an association between the object's
value()
and theed
,md
, andwmd
decoder pointers.Returns: The constructed object.
static bool get_decoders(error_category cat, errno_decoder & ed, message_decoder & md, wmessage_decoder & wmd);
Effects: If
cat.value()
has an association created bynew_category()
, setsed
,md
, andwmd
to the association's respective decoder pointers. Otherwise, no effects.Returns:
true
if the association existed, otherwisefalse
.
system_error
namespace std { namespace tr2 { namespace sys { enum message_action { append_message, no_message }; class system_error : public std::runtime_error { public: explicit system_error(error_code ec); system_error(error_code ec, const std::string & what_arg, message_action ma=append_message); system_error(error_code::value_type ev, error_category ecat); system_error(error_code::value_type ev, error_category ecat, const std::string & what_arg, message_action ma=append_message); virtual ~system_error() throw(); const error_code & code() const throw(); bool message_action append_message() const throw(); const char * what() const throw(); private: string what_msg; // for exposition only }; } // namespace sys } // namespace tr2 } // namespace std
The class system_error
defines the type of objects thrown as
exceptions to report errors originating from the operating system.
system_error(error_code ec);
Effects: Constructs an object of class
system_error
, callsstd::runtime_error(std::string())
.Postcondition:
code() == ec && append_message() == true
.
system_error(error_code ec, const std::string & what_arg, message_action ma=append_message );
Effects: Constructs an object of class
system_error
, callsstd::runtime_error(what_arg)
.Postcondition:
code() == ec && append_message() == ma
.
system_error(error_code::value_type ev, error_category ecat);
Effects: Constructs an object of class
system_error
, callsstd::runtime_error(std::string())
.Postcondition:
code() == error_code(ev, ecat) && append_message() == true
.
system_error(error_code::value_type ev, error_category ecat, const std::string & what_arg, message_action ma=append_message);
Effects: Constructs an object of class
system_error
, callsstd::runtime_error(what_arg)
.Postcondition:
code() == error_code(ev, ecat) && append_message() == ma
.
error_code code() const;
Returns:
ec
orerror_code(ev, ecat)
, from the constructor, as indicated.
bool message_action append_message() const throw();
Returns:
ma
ortrue
, from the constructor, as indicated.
const char * what() const;
Returns: If
!code() || !append_message()
, returnthis->runtime_error::what()
. Otherwise, as if:what_msg = this->runtime_error::what(); if ( !what_msg.empty() ) what_msg += ": "; what_msg += code().message(); return what_msg.c_str();