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_errnoconstant 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 thaterrnoshall 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::othershall be non-zero and not equal to any otherposix_errnovalue.
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_codeinserter to theostreaminclude file, or relax the requirements such that onlycharandwchar_tspecializations 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_type int val, const error_category& cat);
    error_code(posix_errno val);
    // modifiers:
    void assign(value_type int val, const error_category& cat);
    error_code& operator=(posix_errno val);
    void clear();
    // observers:
    value_type int 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_type int 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_typeint 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_errorthat 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_errnovalues 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_categoryandnative_categoryis:extern const error_category& posix_category; extern const error_category& native_category;That doesn't seem vague. The critical member functions of
error_categoryare 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_categoryvirtuals exist to support the equivalenterror_codemember functions. This mechanism unravels iferror_category::posixisn'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::whatandcodedo 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_errortoo. Andsystem_error::whatdoes 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.