Doc. no. N2296=07-0156
Date:
2007-06-24
Project: Programming Language C++
Reply to: Beman Dawes <bdawes@acm.org>
Benjamin Kosnik <bkoz@redhat.com>
Note well: The Proposed resolutions for many of these issues were drafted by Beman Dawes. The issue submitters do not necessarily agree with these PR's.
The clear() function is shown in the synopsis but is otherwise unspecified.
Reported separately by Pete Becker, PJ Plauger, and Benjamin Kosnik.
To 19.4.2.3 Class error_code modifiers [syserr.errcode.modifiers], add:
void clear();
postcondition:
value() == 0 && category() == posix_category
In N2241, enum posix_errno
did not specify values for each
enumeration constant. Instead, a table of equivalence was provided showing the
<cerrno>
E* macro the constant was to be equivalent to. During
editing, that table was folded into the enum for brevity. That was a useful
change, but had the unintended side effect of making it look like <system_error>
must expose the <cerrno> macros
, which was not the intent.
Submitted by PJ Plaguer
Change the form of enum posix_errno
in 19.4 System error
support [syserr] from:
enum posix_errno {
address_family_not_supported = EAFNOSUPPORT,
address_in_use = EADDRINUSE,
...
To:
enum posix_errno {
address_family_not_supported, // EAFNOSUPPORT
address_in_use, // EADDRINUSE
...
At the end of 19.4 System error support [syserr] add:
The value of each
enum posix_errno
constant shall be the same as the equivalent<cerrno>
macro shown as a comment in the above synopsis.
The member function hash_value
should be replaced or supplemented by an
explicit specialization of template class hash (in <functional>) so people can
easily make an unordered container keyed on errors.
Submitted by PJ Plauger.
In 19.4.2.1 Class error_code overview [syserr.errcode.overview], removed:
size_t hash_value(const error_code& ec);
In 19.4.2.6 Class error_code non-member functions [syserr.errcode.nonmembers], remove:
size_t hash_value(const error_code& ec);
Returns: A hash value representing ec.
In 20.5 Function objects [function.objects], paragraph 2, Header <functional> synopsis, add:
template <> struct hash<std::error_code>;
Change 20.5.15 Class template hash [unord.hash] as indicated:
The unordered associative containers defined in clause 23.4 use specializations of hash as the default hash function. This class template is only required to be instantiable for integer types (3.9.1), floating point types (3.9.1), pointer types (8.3.1), and
std::string
,std::u16string
,std::u32string
,andstd::wstring
, andstd::error_code
.
Submitted by Alisdair Meredith.
Change 19.4.2.1 Class error_code overview [syserr.errcode.overview] as indicated:
explicit error_code(posix_errno val);
Change 19.4.2.2 Class error_code constructors [syserr.errcode.constructors] paragraph 6 as indicated:
explicit error_code(posix_errno val);
Objects of class error_code
will commonly be constructed in
very low-level systems code where efficiency is a critical consideration. Thus
static initialization is quite desirable, and would remove the runtime and
code size cost implicit in the Library Working Group's switch to enumeration
style error values.
A possible fix is to apply constexpr
. Note, however, that
since constexpr
is not yet a part of the working paper, and there
is no compiler available for testing, it isn't possible to tell if this change
will actually work as intended.
Submitted by Chris Kohlhoff and Beman Dawes.
If N2235, Generalized Constant Expressions—Revision 5, or
successor has been accepted for inclusion in the Working Paper, in 19.4.2.1 Class error_code overview [syserr.errcode.overview]
and 19.4.2.2 Class error_code constructors [syserr.errcode.constructors], add
constexpr to the constructors.
Class error_category
equality is stated in terms of address
comparison, taking advantage of the C++ language rule that no two objects can
have the same address, and thus avoiding the possibility that independently
created user-defined error categories could inadvertently compare equal.
Thus it makes no sense to allow error_category
objects to be
copyable.
Submitted by Pete Becker.
To 19.4.1.1 Class error_category overview [syserr.errcat.overview] synopsis add:
error_category(const error_category&) = delete; error_category& operator=(const error_category&) = delete;
This also resolves issue 14.
The semantics of the error_code/posix_errno operator==
are
error prone, inherently non-portable, and do not support the most common
intended use case for writing portable code.
For example, say the user writes:
error_code ec = some_operation(...);
if ( ec )
{
if ( ec == io_error )
{
// do something...
}
else
{
// do something else...
}
}
Submitted by Beman Dawes, in response to a question raised by Chris Kohlhoff
Editorial note: The error_code/posix_errno
non-member
functions are currently described in the 19.4.2.5 Class error_code relational
operators [syserr.errcode.relational] section. They should be described in the
section that follows that, 19.4.2.6 Class error_code non-member functions [syserr.errcode.nonmembers].
Change 19.4.2.5 Class error_code relational operators [syserr.errcode.relational] paragraph 5 as indicated:
bool operator==(const error_code& ec, posix_errno en);
bool operator==(posix_errno en, const error_code& ec);Returns:
ec.value() == static_cast<error_code::value_type>(en) && ec.category() == posix_categoryec.posix() == en
.Throws: Nothing.
other
is too general a name to waste on a minor use, and is
not explicit enough.Submitted by Beman Dawes
In 19.4 System error support [syserr] paragraph 2, 19.4.1.2, Class
error_category virtual members [syserr.errcat.virtuals] paragraph 3 (2
places), and the resolution to issue 9 (2 places), change
other
to no_posix_equivalent
.
To 19.4 System error support [syserr], paragraph 2, change as indicated:
enum posix_errno { no_error = 0, address_family_not_supported = EAFNOSUPPORT, ...
The working draft specifies other = EOTHER
in the specification
of posix_errno in 19.4 System error support, with the specification that
EOTHER
is not a POSIX-defined macro in 19.3 Error numbers. Earlier papers
stated that this new macros will be added to the include file cerrno
.
The problem with this is that C++ is hijacking the POSIX macro space, which
should be avoided as future versions of the POSIX standard may add more error
macros, including EOTHER
, but may have it mean something else.
Submitted by Benjamin Kosnik.
Note: The resolution of Issue 8 changes other
to
no_posix_equivalent
.
Change 19.3 Error numbers [errno], paragraph one, as indicated:
The header
<cerrno
> is described in (Table 29). Its contents are the same as the POSIX header<errno.h>
, except thaterrno
shall be defined as a macro, and an additional macro EOTHER shall be defined to represent errors not specified by the POSIX standard. [ Note: The intent is to remain in close alignment with the POSIX standard. —end note ]
From 19.3 Error numbers [errno], Header <cerrno> synopsis, strike
EOTHER.
Change 19.4 System error support [syserr], Header <system_error> synopsis as indicated:
other =
unspecified-valueEOTHER
,
Following 19.4 System error support [syserr], Header <system_error> synopsis, add:
The value of
posix_errno::other
shall be non-zero and not equal to any otherposix_errno
value.
In section 19.4.2.6 Class
error_code non-member functions, an ostream inserter for error_code
is defined for the primary ostream template. This will necessitate the inclusion
of the ostream
include file, which has large dependencies on other
standard library features. The practical result is that the system_error
include, far from being a lightweight, stand-alone error-reporting facility,
will instead come with significant compile time cost.
Submitted by Benjamin Kosnik.
Fix: Move the
error_code
inserter to theostream
include file, or relax the requirements such that onlychar
andwchar_t
specializations are required.
To be supplied.
error_code::value_type
with circular
dependencies.Section 19.4.2.1 specifies
error_code::value_type
as typedef int_least32_t value_type;
.
However, this type is used in error_category
, which has to be
defined before any of the trivial members in error_code
can be made
inline.
In addition, this complexity results in unsightly casting in the
error_code
relational operators and constructor specifications.
Possible Fix: Assume error_code::value_type
is of type
int
, as specified by both C and POSIX.
Submitted by Benjamin Kosnik.
Beman Dawes comments: The typedef is a historical artifact. An int is sufficient for all operating systems I am aware of. I support the change.
Change 19.4.2.1 Class error_code overview [syserr.errcode.overview] as indicated:
namespace std { class error_code { public:typedef int_least32_t value_type;// constructors: error_code(); error_code(value_typeint val, const error_category& cat); error_code(posix_errno val); // modifiers: void assign(value_typeint val, const error_category& cat); error_code& operator=(posix_errno val); void clear(); // observers:value_typeint value() const; cont error_category& category() const; posix_errno posix() const; string message() const; wstring wmessage() const; operator unspecified-bool-type const; // relational operators: bool operator==(const error_code& rhs) const; bool operator!=(const error_code& rhs) const; private:value_typeint val_; // exposition only const error_category& cat_; // exposition only }; template <class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& os, const error_code& ec); size_t hash_value(const error_code& ec); } // namespace std
Change 19.4.2.2 Class error_code constructors [syserr.errcode.constructors] as indicated:
error_code(
value_typeint val, const error_category& cat);
Change 19.4.2.3 Class error_code modifiers [syserr.errcode.modifiers] as indicated:
void assign(
value_typeint val, const error_category& cat);
Change 19.4.2.1 Class error_code overview [syserr.errcode.overview] as indicated:
value_type
int value() const;
In 19.4.1.2 Class
error_category virtual members, all member functions are defined to not throw,
but do not have throw()
specifications.
The same hold for error_code
member functions that are modifiers
and observers. i.e, sections 19.4.2.3
and 19.4.2.4.
Submitted by Benjamin Kosnik.
Proposed Fix: Add in missing
throw()
specifications.
No action necessary.
The Working Paper is inconsistent in its use of throw()
specifications. Many LWG members prefer the "Throws: Nothing" specification as
used in the current working paper wording for diagnostics.
system_error
constructor.All existing classes derived from std::exception
provide either
a default constructor or a constructor taking a single const std::string&
parameter. The current specification for system_error
breaks with
this.
Submitted by Benjamin Kosnik.
Proposed Fix: Add a constructor to
system_error
that takes aconst std::string&
argument.
No action necessary.
The design of the constructors, including order of
arguments, was a considered
decision after discussion with Peter Dimov and others on the Boost list. A
primary objective of system_error
is to report an
error_code
. We don't want to encourage construction of
system_error
objects that don't have one. Thus the constructors all
take error_code
or equivalent arguments first in addition to the
what string argument. Not supplying a default constructor avoids the
nonsensical construction of system_error representing "no error".
error_category
equality via address comparison.Section 19.4.1.3 Class
error_category non-virtual members specifies address comparisons between
error_category
base objects to determine equality and inequality. This
can be fragile or difficult in shared memory or distributed systems, and may
lead to incorrect results for equivalent error_category
objects.
Submitted by Benjamin Kosnik.
Fix: Equality compare on internal details of the message catalog characteristics.
Resolved by Issue 6: Class error_category should be non-copyable. No further action needed.
error_code::value_types
constants and
user-defined error_category
objects.Section 19.4 specifies posix_errno
as an enum. As such, there is
no way to extend it for native error values, which will presumably be in the
form of another enum, in some user-defined space.
Yes, but that seems unavoidable fallout from the use of an enum as mandated by the LWG. Also, it is possible, if tedious, for another enum to refer to the
posix_errno
values one-by-one.
Section 19.4.1.4 Error category
objects vaguely specifies posix_category
and native_category
as external objects. As such, the implementation details are likely to remain
private, making simple derivation and extension tricky or difficult.
The specification of
posix_category
andnative_category
is:extern const error_category& posix_category; extern const error_category& native_category;That doesn't seem vague. The critical member functions of
error_category
are public virtuals; that seems sufficient access to functionality without violating encapsulation.
Submitted by Benjamin Kosnik.
No action necessary. See above comments for rationale.
error_category
.Should posix_category
and native_category
be able
to have the same address?
In theory, yes. In practice, no, because no real operating system exactly implements the POSIX specification. Real operating systems at the minimum add some of their own error codes.
Should the member function error_category::posix
exist for the
predefined object posix_category
? Isn't this a no-op, and best
added to the class implementing native_category
?
The
error_category
virtuals exist to support the equivalenterror_code
member functions. This mechanism unravels iferror_category::posix
isn't present for all error categories.
Should the division be between underlying system errors needed by the C++0x standard library and user-defined error messages, instead of between POSIX and native?
Early versions of the current design divided the world along standard library / native lines. The design evolved into a POSIX / native / user-defined breakdown because it met specific needs of users and third-party library suppliers, who must deal with a variety of real-world use cases. That isn't to say another design wouldn't work, but this design is known to work and represents successful existing practice.
Submitted by Benjamin Kosnik.
No action necessary. See above comments for rationale.
error_category::message
member functions.Section 19.4.1.2 Class
error_category virtual members defines members message
and
wmessage
, and notes an intention to provide a locale-specific string.
However, there is no indication that this is integrated into the existing
standard library infrastructure for locale, ie std::locale
.
There are two distinct issues: one, construction of error_category
would have to take some kind of std::locale
parameter, some kind of
getter/setter would have to exist to provide locale data, or message
would have to take a std::locale
argument. This last option would
require serious re-work of the system_error::what
member function.
The second issue is code conversion so that wmessage
could
return a wide string from a message catalog. The use case for this is
theoretical at the moment, as wide-character message catalogs are not known. For
this, std::codecvt
would be the preferred mechanism, and that
depends on three template parameters. If this route is followed, it may make
sense to templatize the entire class, and separate out message
for
char
instantiations and wmessage
for wchar_t
instantiations.
Note that error_code
has these same member functions, which
forward to the error_category
member functions, so this could be
considered a defect in both class specifications.
Submitted by Benjamin Kosnik.
Change 19.4.1.1 Class error_category overview [syserr.errcat.overview] paragraph 1 as indicated:
virtual wstring wmessage(error_code::value_type ev) const = 0;
Change 19.4.1.2 Class error_category virtual members [syserr.errcat.virtuals] paragraph 4 as indicated:
virtual wstring wmessage(error_code::value_type ev) const = 0;
Change 19.4.2.1 Class error_code overview [syserr.errcode.overview] paragraph 1 as indicated:
wstring wmessage() const;
Change 19.4.2.4 Class error_code observers [syserr.errcode.observers] beginning at paragraph 8 as indicated:
wstring wmessage() const;
Returns:category().wmessage(value())
.
Throws: Nothing.
For the locale issue, no action necessary. This underspecification of "locale-specific" was deliberate; there doesn't appear to be a solution ready for standardization, and in the absence of a standard solution, library suppliers know best how to meet their user's needs.
Rationale for removing wmessage: It is difficult or impossible to implement well on some operating systems. None of the current standard exception classes worry about wide messages, so a fix in one particular place only probably isn't the right approach.
system_error::what
and constructorsIn 19.4.3.2 Class system_error
members, the constructor definitions and what
specification collude
to force exception-unsafe behavior, and multiple std::string
data
members.
Exception safety is dealt with by the proposed resolution. The data members are not specified; implementations are free to use a std::string or some completely different mechanism. Implementations will presumably use lazy evaluation, so much of the cost will only occur if what() is actually called. No action necessary.
This in effect mandates elaborate string modification as part of
system_error::what
, which may cause unanticipated exceptions to occur, in
addition to being inefficient.
system_error::what
andcode
do specify throw() in the synopsis to deal with the exception issue, but not in the member descriptions. See proposed resolution. The string modification is extremely valuable to users, and any inefficiency is minor compared to the general overhead of an exception being thrown. No additional action necessary.
These specifications are a break with the existing stdexcept
requirements and the exception hierarchy design philosophy: by making what
virtual, users can reasonably expect to have derived classes with different
return strings from what
. Indeed, that's the point.
what() is virtual in the base class, so is virtual in class
system_error
too. Andsystem_error::what
does normally return a different string thanruntime_error::what
. No action necessary.
In addition, with all these additional requirements, there still exists no way to pass in locale-specific strings.
See issue 17.
Change 19.4.3.2 Class system_error members [syserr.syserr.members], paragraph 4, as indicated:
const error_code& code() const throw();
Change 19.4.3.2 Class system_error members [syserr.syserr.members], paragraph 5, as indicated:
const char *what() const throw();
No additional action necessary. See above comments for rationale.
The Boost version provides operator<
for both, allowing objects of class
error_code
to
be easily used as keys for associative containers. I can't remember any rationale for removing them from
the proposal; perhaps it was a simple oversight. It seems to me they should be
provided as a courtesy if nothing else. On the other hand, users can provide
their own compare functions if needed.
Submitted by Beman Dawes.
To be supplied.