diff --git a/doc/diagnostic_information.html b/doc/diagnostic_information.html index 1ec4a97..9941f22 100644 --- a/doc/diagnostic_information.html +++ b/doc/diagnostic_information.html @@ -63,13 +63,13 @@ else return <unspecified-string-value>;
this is a possible output from the diagnostic_information function, as used in libs/exception/example/example_io.cpp:
-example_io.cpp(83): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *) +example_io.cpp(70): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *) Dynamic exception type: class boost::exception_detail::clone_impl<class fopen_error> std::exception::what: example_io error -[struct tag_errno *] = 2, OS says "No such file or directory" -[struct tag_file_name *] = tmp1.txt -[struct tag_function *] = fopen -[struct tag_open_mode *] = rb+[struct boost::errinfo_api_function_ *] = fopen +[struct boost::errinfo_errno_ *] = 2, "No such file or directory" +[struct boost::errinfo_file_name_ *] = tmp1.txt +[struct boost::errinfo_file_open_mode_ *] = rb
this is a possible output from the diagnostic_information function, as used in libs/exception/example/example_io.cpp:
-example_io.cpp(83): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *) +example_io.cpp(70): Throw in function class boost::shared_ptr<struct _iobuf> __cdecl my_fopen(const char *,const char *) Dynamic exception type: class boost::exception_detail::clone_impl<class fopen_error> std::exception::what: example_io error -[struct tag_errno *] = 2, OS says "No such file or directory" -[struct tag_file_name *] = tmp1.txt -[struct tag_function *] = fopen -[struct tag_open_mode *] = rb+[struct boost::errinfo_api_function_ *] = fopen +[struct boost::errinfo_errno_ *] = 2, "No such file or directory" +[struct boost::errinfo_file_name_ *] = tmp1.txt +[struct boost::errinfo_file_open_mode_ *] = rb
Here is how cloning can be enabled in a throw-expression (15.1):
#include <boost/exception/info.hpp> +#include <boost/exception/errinfo_errno.hpp> #include <stdio.h> #include <errno.h> -typedef boost::error_info<struct tag_errno,int> errno_info; - class file_read_error: public boost::exception { }; void @@ -40,7 +39,7 @@ file_read( FILE * f, void * buffer, size_t size ) { if( size!=fread(buffer,1,size,f) ) throw boost::enable_current_exception(file_read_error()) << - errno_info(errno); + boost::errinfo_errno(errno); }
Of course, enable_current_exception may be used with any exception type; there is no requirement that it should derive from boost::exception.
The following example demonstrates how errno can be stored in exception objects using Boost Exception:
-#include <boost/exception.hpp> -#include <errno.h> ++#include <boost/exception/all.hpp> #include <iostream> -typedef boost::error_info<struct tag_errno,int> errno_info; //(1) +typedef boost::error_info<struct tag_my_info,int> my_info; //(1) class my_error: public boost::exception, public std::exception { }; //(2) void f() { - throw my_error() << errno_info(errno); //(3) - } --First, we instantiate the error_info template using a unique identifier -- tag_errno, and the type of the info it identifies -- int. This provides compile-time type safety for the various values stored in exception objects.
+ throw my_error() << my_info(42); //(3) + }
First, we instantiate the error_info template using a unique identifier -- tag_my_info, and the type of the info it identifies -- int. This provides compile-time type safety for the various values stored in exception objects.
Second, we define class my_error, which derives from boost::exception.
Finally, (3) illustrates how the typedef from (1) can be used with operator<< to store values in exception objects at the point of the throw.
-The stored errno value can be recovered at a later time like this:
+The stored my_info value can be recovered at a later time like this:
// ...continued void @@ -59,8 +57,8 @@ g() catch( my_error & x ) { - if( int const * err=boost::get_error_info<errno_info>(x) ) - std::cerr << "Error code: " << *err; + if( int const * mi=boost::get_error_info<my_info>(x) ) + std::cerr << "My info: " << *mi; } }
The get_error_info function template is instantiated with the typedef from (1), and is passed an exception object of a polymorphic type. If the exception object contains the requested value, err will point to it; otherwise a null pointer is returned.
@@ -75,28 +73,25 @@ file_read( FILE * f, void * buffer, size_t size ) }How can the file_read function pass a file name to the exception type constructor? All it has is a FILE handle.
Using boost::exception allows us to free the file_read function from the burden of storing the file name in exceptions it throws:
-#include <boost/exception.hpp> +boost/exception/all.hpp> +#include <boost/shared_ptr.hpp> #include <stdio.h> #include <errno.h> -typedef boost::error_info<struct tag_errno,int> errno_info; - class file_read_error: public boost::exception { }; void file_read( FILE * f, void * buffer, size_t size ) { if( size!=fread(buffer,1,size,f) ) - throw file_read_error() << errno_info(errno); + throw file_read_error() << boost::errinfo_errno(errno); }If file_read detects a failure, it throws an exception which contains the information that is available at the time, namely the errno. Other relevant information, such as the file name, can be added in a context higher up the call stack, where it is known naturally:
-#include <boost/exception.hpp> +#include <boost/exception/all.hpp> #include <boost/shared_ptr.hpp> #include <stdio.h> #include <string> -typedef boost::error_info<struct tag_file_name,std::string> file_name_info; - boost::shared_ptr<FILE> file_open( char const * file_name, char const * mode ); void file_read( FILE * f, void * buffer, size_t size ); @@ -113,7 +108,7 @@ parse_file( char const * file_name ) catch( boost::exception & e ) { - e << file_name_info(file_name); + e << boost::errinfo_file_name(file_name); throw; } }@@ -122,15 +117,15 @@ parse_file( char const * file_name )
The code snippet below demonstrates how boost::tuple can be used to bundle the name of the function that failed, together with the reported errno so that they can be added to exception objects more conveniently together:
#include <boost/exception/info_tuple.hpp> +#include <boost/exception/errinfo_file_name.hpp> +#include <boost/exception/errinfo_api_function.hpp> +#include <boost/exception/errinfo_errno.hpp> #include <boost/shared_ptr.hpp> #include <stdio.h> #include <string> #include <errno.h> -typedef boost::error_info<struct tag_file_name,std::string> file_name_info; -typedef boost::error_info<struct tag_function,char const *> function_info; -typedef boost::error_info<struct tag_errno,int> errno_info; -typedef boost::tuple<function_info,errno_info> clib_failure; +typedef boost::tuple<boost::errinfo_api_function,boost::errinfo_errno> clib_failure; class file_open_error: public boost::exception { }; @@ -141,7 +136,7 @@ file_open( char const * name, char const * mode ) return boost::shared_ptr<FILE>(f,fclose); else throw file_open_error() << - file_name_info(name) << + boost::errinfo_file_name(name) << clib_failure("fopen",errno); }
Note that the members of a boost::tuple are stored separately in exception objects; they can only be retrieved individually, using get_error_info.
diff --git a/example/cloning_1.cpp b/example/cloning_1.cpp index 4e23a62..356d741 100644 --- a/example/cloning_1.cpp +++ b/example/cloning_1.cpp @@ -6,11 +6,10 @@ //This example shows how to enable cloning when throwing a boost::exception. #include