# nested_exception.h

Go to the documentation of this file.

    00001 // Nested Exception support header (nested_exception class) for -*- C++ -*-
    00002
    00003 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 3, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // Under Section 7 of GPL version 3, you are granted additional
    00017 // permissions described in the GCC Runtime Library Exception, version
    00018 // 3.1, as published by the Free Software Foundation.
    00019
    00020 // You should have received a copy of the GNU General Public License and
    00021 // a copy of the GCC Runtime Library Exception along with this program;
    00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    00023 // <http://www.gnu.org/licenses/>.
    00024
    00025 /** @file nested_exception.h
    00026  *  This is an internal header file, included by other headers and the
    00027  *  implementation. You should not attempt to use it directly.
    00028  */
    00029
    00030 #ifndef _GLIBCXX_NESTED_EXCEPTION_H
    00031 #define _GLIBCXX_NESTED_EXCEPTION_H 1
    00032
    00033 #pragma GCC visibility push(default)
    00034
    00035 #ifndef __GXX_EXPERIMENTAL_CXX0X__
    00036 # include <bits/c++0x_warning.h>
    00037 #else
    00038
    00039 #include <bits/c++config.h>
    00040
    00041 #if !defined(_GLIBCXX_ATOMIC_BUILTINS_4)
    00042 #  error This platform does not support exception propagation.
    00043 #endif
    00044
    00045 extern "C++" {
    00046
    00047 namespace std
    00048 {
    00049   /**
    00050    * @addtogroup exceptions
    00051    * @{
    00052    */
    00053
    00054   /// Exception class with exception_ptr data member.
    00055   class nested_exception
    00056   {
    00057     exception_ptr _M_ptr;
    00058
    00059   public:
    00060     nested_exception() throw() : _M_ptr(current_exception()) { }
    00061
    00062     nested_exception(const nested_exception&) = default;
    00063
    00064     nested_exception& operator=(const nested_exception&) = default;
    00065
    00066     inline virtual ~nested_exception();
    00067
    00068     void
    00069     rethrow_nested() const __attribute__ ((__noreturn__))
    00070     { rethrow_exception(_M_ptr); }
    00071
    00072     exception_ptr
    00073     nested_ptr() const
    00074     { return _M_ptr; }
    00075   };
    00076
    00077   inline nested_exception::~nested_exception() = default;
    00078
    00079   template<typename _Except>
    00080     struct _Nested_exception : public _Except, public nested_exception
    00081     {
    00082       explicit _Nested_exception(_Except&& __ex)
    00083       : _Except(static_cast<_Except&&>(__ex))
    00084       { }
    00085     };
    00086
    00087   template<typename _Ex>
    00088     struct __get_nested_helper
    00089     {
    00090       static const nested_exception*
    00091       _S_get(const _Ex& __ex)
    00092       { return dynamic_cast<const nested_exception*>(&__ex); }
    00093     };
    00094
    00095   template<typename _Ex>
    00096     struct __get_nested_helper<_Ex*>
    00097     {
    00098       static const nested_exception*
    00099       _S_get(const _Ex* __ex)
    00100       { return dynamic_cast<const nested_exception*>(__ex); }
    00101     };
    00102
    00103   template<typename _Ex>
    00104     inline const nested_exception*
    00105     __get_nested_exception(const _Ex& __ex)
    00106     { return __get_nested_helper<_Ex>::_S_get(__ex); }
    00107
    00108   template<typename _Ex>
    00109     void
    00110     __throw_with_nested(_Ex&&, const nested_exception* = 0)
    00111     __attribute__ ((__noreturn__));
    00112
    00113   template<typename _Ex>
    00114     void
    00115     __throw_with_nested(_Ex&&, ...) __attribute__ ((__noreturn__));
    00116
    00117   // This function should never be called, but is needed to avoid a warning
    00118   // about ambiguous base classes when instantiating throw_with_nested<_Ex>()
    00119   // with a type that has an accessible nested_exception base.
    00120   template<typename _Ex>
    00121     inline void
    00122     __throw_with_nested(_Ex&& __ex, const nested_exception* = 0)
    00123     { throw __ex; }
    00124
    00125   template<typename _Ex>
    00126     inline void
    00127     __throw_with_nested(_Ex&& __ex, ...)
    00128     { throw _Nested_exception<_Ex>(static_cast<_Ex&&>(__ex)); }
    00129
    00130   template<typename _Ex>
    00131     void
    00132     throw_with_nested(_Ex __ex) __attribute__ ((__noreturn__));
    00133
    00134   /// If @p __ex is derived from nested_exception, @p __ex.
    00135   /// Else, an implementation-defined object derived from both.
    00136   template<typename _Ex>
    00137     inline void
    00138     throw_with_nested(_Ex __ex)
    00139     {
    00140       if (__get_nested_exception(__ex))
    00141         throw __ex;
    00142       __throw_with_nested(static_cast<_Ex&&>(__ex), &__ex);
    00143     }
    00144
    00145   /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested().
    00146   template<typename _Ex>
    00147     inline void
    00148     rethrow_if_nested(const _Ex& __ex)
    00149     {
    00150       if (const nested_exception* __nested = __get_nested_exception(__ex))
    00151         __nested->rethrow_nested();
    00152     }
    00153
    00154   /// Overload, See N2619
    00155   inline void
    00156   rethrow_if_nested(const nested_exception& __ex)
    00157   { __ex.rethrow_nested(); }
    00158
    00159   // @} group exceptions
    00160 } // namespace std
    00161
    00162 } // extern "C++"
    00163
    00164 #endif // __GXX_EXPERIMENTAL_CXX0X__
    00165
    00166 #pragma GCC visibility pop
    00167
    00168 #endif // _GLIBCXX_NESTED_EXCEPTION_H