std::exception
    
      C++ supports throwing objects of user-defined types, which allows arbitrary data to be stored in exception objects
      at the point of the throw. Unfortunately at that time we may not have available all of the data that is needed
      at the catch site to properly deal with the error. However, that data is usually available in contexts
      higher in the call stack, between the throw and the catch that handles the exception.
    
      This document proposes extending std::exception to allow exception-neutral contexts to intercept
      any std::exception object and store into it arbitrary additional data needed to handle the exception (the propagation of
      the original exception object can then be resumed by a throw without argument.)
    
      To illustrate the problem, consider the following example of a catch statement that handles an exception of a user-defined type
      file_read_error:
    
catch( file_read_error & e )
{
  std::cerr << e.file_name();
}
    
    
      And the matching throw:
    
void read_file( FILE * f )
{
  ....
  size_t nr=fread(buf,1,count,f);
  if( ferror(f) )
    throw file_read_error(???);
  ....
}
    
    
      The issue is that the catch site needs a file name, but at the point of the throw
      a file name is not available (only a FILE pointer is.)
    
      Consider that the error might be detected in a library which can not assume that a meaningful name is
      available for any FILE it reads, even if a program that uses the library could reasonably make the same
      assumption.
    
      The proposed extension to std::exception allows a program to augment library exceptions
      with program-specific information required to properly handle them:
    
      struct errinfo_file_name { typedef std::string type; };
void process_file( char const * name )
{
  try
  {
    if( FILE * fp=fopen(name,"rt") )
    {
      std::shared_ptr<FILE> f(fp,fclose);
      ....
      read_file(fp); //throws types deriving from std::exception
      ....
    }
    else
      throw file_open_error();
  }
  catch( std::exception & e )
  {
    e.set<errinfo_file_name>(name);
    throw;
  }
}
    
    The handler can retrieve the file name using the following syntax:
      catch( file_io_error & e ) //derives (possibly indirectly) from std::exception
{
  std::cerr << "I/O error!\n";
  std::string const * fn=e.get<errinfo_file_name>(e);
  assert(fn!=0); //In this program all files have names.
  std::cerr << "File name: " << *fn << "\n";
}
    
    
      Extending std::exception as proposed is compatible with existing code and does not affect any other parts
      of the standard library, except possibly make_exception_ptr and current_exception.
    
          Add to std::exception the following member functions:
        
template <class Tag> void set( typename Tag::type const & x );
          Requirements: x shall be copyable.
        
          Effects: A copy of x is stored in this. If this already
          has a value stored under the specified Tag, the original value is overwritten.
        
          Postconditions: get<Tag>() returns a pointer to the stored copy of x.
        
          Throws: std::bad_alloc or any exception thrown by T's copy or move constructor.
        
          Note: It is permitted for copies of a std::exception object to share storage
          for the objects stored by set<>, except for copies created by std::make_exception_ptr or
          std::current_exception. Therefore calling set<> on copies of a std::exception
          is not thread-safe unless the copies were created by std::make_exception_ptr or std::current_exception.
        
template <class Tag> typename Tag::type const * get() const;
          Returns: If set<Tag> was called to store a copy of an object of type typename Tag::type
          in this, get<Tag> returns a pointer to that copy; otherwise it returns 0.
        
Throws: does not throw.
          Note: Destroying the exception object or calling set<> invalidates the returned pointer.
        
std::string diagnostic_information() const;
          Returns: A string of unspecified format that contains human-readable diagnostic information about this.
        
          Throws: May throw std::bad_alloc or any exception thrown in the attempt to convert to string any of the objects
          stored in this by set<>.
        
Notes:
              Implementations are encouraged to include in the returned string information about the dynamic type of this,
              for example by means of typeid(*this).name().
            
              Implementations are encouraged to include in the returned string the string returned by what.
            
              Implementations are encouraged to include in the returned string information collected by __FILE__ and __LINE__
              at the point of the throw. The formatting may match the format of compile-time diagnostic messages.
            
              Implementations are encouraged to include in the returned string the name of the function contaning the throw.
            
              At the time diagnostic_information is called, implementations may convert to string any of the objects
              stored in this by set<>, by calling a suitable operator<< overload that takes
              std::ostream object on the left and typename Tag::type object on the right, bound at the point of
              instantiation of set<Tag>. Implementations are not allowed to issue a diagnostic if a suitable overload could
              not be bound.
            
              At the time diagnostic_information is called, objects for which a suitable operator<< overload
              could not be bound may be converted to string if a different reasonable string conversion is possible. For example,
              if an operator<< overload suitable for converting objects of type T can be bound, a
              std::vector<T> may be converted to string by calling that overload for each element of the vector
              and concatenating the results.
            
              At the time diagnostic_information is called, objects of type exception_ptr stored in this
              by set<> may be converted to string by nesting the result of calling diagnostic_information
              on the object they point to.
            
              Implementations are encouraged to pair each converted to string object with a string representation of its tag type, for example
              by means of typeid(Tag).name(), and to include both in the returned string. If a given object could not be reasonably
              converted to string, an implementation-specified stub string may be used instead.
            
              Implementations may include in the returned string any other relevant information, such as a stack trace
              collected at the point of the throw.
            
Example:
example_io.cpp(70): Throw in function class std::shared_ptr<FILE> open_file(const char *,const char *) Dynamic exception type: struct file_open_error what: example_io error errinfo_api_function = fopen errinfo_errno = 2, "No such file or directory" errinfo_file_name = tmp1.txt
          Add the following note to the specification of current_exception (18.8.5 [propagation]):
        
              Note: If the current exception derives from std::exception, the exception object that is propagated
              when the returned exception_ptr is passed to rethrow_exception shall include copies of
              all objects stored in the original exception object by std::exception::set<>.
            
          Add the following note to the specification of make_exception_ptr (18.8.5 [propagation]):
        
              Note: If E derives from std::exception, the exception object that is propagated
              when the returned exception_ptr is passed to rethrow_exception shall include copies of
              all objects stored in the original exception object by std::exception::set<>.
            
A proof of concept implementation is available in Boost. See boost/exception/N3757.hpp and libs/exception/test/N3757_test.cpp in http://svn.boost.org/svn/boost/trunk.
This proposal is based on the Boost Exception library and incorporates valuable feedback from the Boost community. Special thanks to Peter Dimov and Dave Abrahams.