exceptions.hpp

来自「CGAL is a collaborative effort of severa」· HPP 代码 · 共 1,741 行 · 第 1/4 页

HPP
1,741
字号
// -- Boost Lambda Library -- exceptions.hpp ----------------//// Copyright (C) 2000 Gary Powell (gwpowell@hotmail.com)// Copyright (C) 1999, 2000 Jaakko J鋜vi (jaakko.jarvi@cs.utu.fi)//// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)//// For more information, see http://www.boost.org // -----------------------------------------------------#if !defined(BOOST_LAMBDA_EXCEPTIONS_HPP)#define BOOST_LAMBDA_EXCEPTIONS_HPP#include "boost/lambda/detail/control_constructs_common.hpp"namespace boost { namespace lambda {typedef lambda_functor<placeholder<EXCEPTION> > placeholderE_type;namespace {  boost::lambda::placeholderE_type freeE;  boost::lambda::placeholderE_type& _e = freeE;        }// -- exception related actions -------------------// catch actions.template <class Catch1, class Catch2 = null_type, class Catch3 = null_type,           class Catch4 = null_type, class Catch5 = null_type,           class Catch6 = null_type, class Catch7 = null_type,           class Catch8 = null_type, class Catch9 = null_type,           class Catch10 = null_type>struct catch_action {};struct catch_all_action {};template<class CatchActions>struct return_try_catch_action {};template<class CatchActions>struct try_catch_action {};// rethrow actionsstruct throw_new_action {};struct rethrow_action {};template<class ThrowType> class throw_action;template<>struct throw_action<rethrow_action> {  template<class RET>  static RET apply() {    throw;  }};template<> struct throw_action<throw_new_action> {  template<class RET, class T>  static RET apply(T& t) {    throw t;  }};// return types for throw_actions --------------------------------------------template<class T, class Any>struct return_type_N<throw_action<T>, Any> {  typedef void type;};// return types deductions -------------------------------------------------// the return type of try_catch is the return type of the try lambda_functor// (the return types of try and catch parts must match unless try returns void// or the catch part throws for sure)// NOTE, the exception placeholder deduction rule is defined // in return_type_traits.hpp// defined in control_constructsclass ifthenelse_action;namespace detail {// Templates for deducing, wether a lambda_functor throws inevitably of not -// This mechanism is needed to make the compiler happy about// return types of try and catch parts. // a lambda_functor throws for sure if://  - it is a throw expression//  - it is a comma expression, and one of its arguments throws for sure//  - it is an if_then_else expression and either the if statement or both //  the then and  else throw.// (there are other cases as well, but we do not cover them)// e.g. _1 + (rethrow(), 3) does throw for sure but this is not checked// This implies, that in such a case, the return types of try and catch parts // must match if the try part returns other than void.// (Such checks could be done though)template <class Arg> struct throws_for_sure_phase2 {  static const bool value = false;};template <int N, class ThrowType, class Args> struct throws_for_sure_phase2<  lambda_functor<     lambda_functor_base<action<N, throw_action<ThrowType> >, Args>   > >{  static const bool value = true;};// Both then and else or the if throw of an if_then_else.template <class Args> struct throws_for_sure_phase2<  lambda_functor<    lambda_functor_base<      ifthenelse_action, Args    >   > >{  static const bool value =    throws_for_sure_phase2<      typename boost::tuples::element<0, Args>::type>::value    ||      (       throws_for_sure_phase2<         typename boost::tuples::element<1, Args>::type       >::value       &&        throws_for_sure_phase2<         typename boost::tuples::element<2, Args>::type       >::value    );};template <class Args> struct throws_for_sure_phase2<  lambda_functor<     lambda_functor_base< other_action<comma_action>, Args>   > >{  static const bool value =    throws_for_sure_phase2<      typename boost::tuples::element<0, Args>::type    >::value    ||     throws_for_sure_phase2<      typename boost::tuples::element<1, Args>::type    >::value;};  // get rid of any qualifiers and references  // lambda_functors should be stored like that, so this is to be extra sure template <class Arg> struct throws_for_sure {  static const bool value     = throws_for_sure_phase2<        typename detail::remove_reference_and_cv<Arg>::type      >::value;};// -- return_or_throw templates -----------------------------// false case, catch and try return types are incompatible// Now the catch part must throw for sure, otherwise a compile time error// occurs.template<bool is_conversion>struct return_or_throw_phase2 {  template<class RET, class Arg, CALL_TEMPLATE_ARGS>  static RET call(Arg& arg, CALL_FORMAL_ARGS) {    BOOST_STATIC_ASSERT(throws_for_sure<Arg>::value);    detail::select(arg, CALL_ACTUAL_ARGS); // this line throws    throw 1; // this line is never performed, hence 1 is just a dummy             // The line is needed to make compiler happy and not require             // a matching return type  }};// the try and catch return types are compatibletemplate<>struct return_or_throw_phase2<true> {  template<class RET, class Arg, CALL_TEMPLATE_ARGS>  static RET call(Arg& arg, CALL_FORMAL_ARGS) {    return detail::select(arg, CALL_ACTUAL_ARGS);  }};// the non-void case. Try part returns a value, so catch parts must // return a value of the same type or throwtemplate<class RET, class ARG>struct return_or_throw {  // Arg should be equal to ARG except that ARG may be a reference  // to be sure, that there are no suprises for peculiarly defined return types  // ARG is passed explicitely  template<class Arg, CALL_TEMPLATE_ARGS>  static RET call(Arg& arg, CALL_FORMAL_ARGS)  {            //    typedef typename Arg::return_type<ARG, open_args<A&, B&, C&> >::type RT;            typedef typename as_lambda_functor<ARG>::type lf_type;    typedef typename lf_type::inherited::template       sig<tuple<CALL_REFERENCE_TYPES> >::type RT;      return       return_or_throw_phase2<        ::boost::is_convertible<RT, RET>::value      >::template call<RET>(arg, CALL_ACTUAL_ARGS);  }};// if try part returns void, we do not return the catch parts eithertemplate<class ARG>struct return_or_throw<void, ARG> {  template<class Arg, CALL_TEMPLATE_ARGS>  static void call(Arg& arg, CALL_FORMAL_ARGS) { detail::select(arg, CALL_ACTUAL_ARGS); }};} // end detail// Throwing exceptions ---------------------------------------------namespace detail {template <class T> struct catch_block {}; struct catch_all_block {};template <class T> struct exception_catch_tag {};// normal catch block is represented as// tagged_lambda_functor<exception_catch_tag<catch_type<T> > >, LambdaFunctor>  // the default catch all block as:// tagged_lambda_functor<exception_catch_tag<catch_all_block> >, LambdaFunctor>} // end detail// the code is RETHROW, this ensures that a compile time error results, // if this lambda_functor is used outside a delayed catch_expressioninline const lambda_functor<   lambda_functor_base<     action<0, throw_action<rethrow_action> >,     null_type  > >rethrow() {   return       lambda_functor_base<         action<0, throw_action<rethrow_action> >,        null_type      >     ( null_type() );}template <class Arg1>inline const lambda_functor<  lambda_functor_base<     action<1, throw_action<throw_new_action> >,     tuple<typename const_copy_argument<const Arg1>::type>  > >throw_exception(const Arg1& a1) {   return       lambda_functor_base<         action<1, throw_action<throw_new_action> >,         tuple<typename const_copy_argument<const Arg1>::type>      >     ( tuple<typename const_copy_argument<const Arg1>::type>(a1));}// create catch blockstemplate <class CatchType, class Arg>inline const tagged_lambda_functor<  detail::exception_catch_tag<detail::catch_block<CatchType> >,   lambda_functor<Arg> > catch_exception(const lambda_functor<Arg>& a) {   // the third placeholder cannot be used in catch_exception  //    BOOST_STATIC_ASSERT((!has_placeholder<Arg, THIRD>::value));  return     tagged_lambda_functor<      detail::exception_catch_tag<detail::catch_block<CatchType> >,       lambda_functor<Arg>     > (a);}// catch and do nothing case.template <class CatchType>inline const tagged_lambda_functor<  detail::exception_catch_tag<detail::catch_block<CatchType> >,   lambda_functor<    lambda_functor_base<      do_nothing_action,      null_type    >   >>catch_exception() {   return     tagged_lambda_functor<      detail::exception_catch_tag<detail::catch_block<CatchType> >,       lambda_functor<        lambda_functor_base<          do_nothing_action,          null_type        >       >    > ();}// create catch(...) blockstemplate <class Arg>inline const tagged_lambda_functor<  detail::exception_catch_tag<detail::catch_all_block>,   lambda_functor<Arg> > catch_all(const lambda_functor<Arg>& a) {   // the third placeholder cannot be used in catch_exception  BOOST_STATIC_ASSERT((!has_placeholder<Arg, THIRD>::value));  return     tagged_lambda_functor<      detail::exception_catch_tag<detail::catch_all_block>,       lambda_functor<Arg>     > (a);}// catch(...) and do nothing case.inline const tagged_lambda_functor<  detail::exception_catch_tag<detail::catch_all_block>,   lambda_functor<    lambda_functor_base<      do_nothing_action,      null_type    >   >>catch_all() {   return     tagged_lambda_functor<      detail::exception_catch_tag<detail::catch_all_block>,       lambda_functor<        lambda_functor_base<          do_nothing_action,          null_type        >       >     > ();}// try_catch functions --------------------------------// The second -> N argument(s) are must be catch lambda_functors template <class TryArg, class Catch1, class LF1>inline const lambda_functor<   lambda_functor_base<     action<2, try_catch_action<catch_action<Catch1> > >,     tuple<lambda_functor<TryArg>, LF1>  > >try_catch(  const lambda_functor<TryArg>& a1,   const tagged_lambda_functor<detail::exception_catch_tag<Catch1>, LF1>& a2) {   return     lambda_functor_base<       action<2, try_catch_action<catch_action<Catch1> > >,       tuple<lambda_functor<TryArg>, LF1>    >     ( tuple< lambda_functor<TryArg>, LF1>(a1, a2));}template <class TryArg, class Catch1, class LF1,                         class Catch2, class LF2>inline const   lambda_functor<     lambda_functor_base<       action<3, try_catch_action<catch_action<detail::catch_block<Catch1>, Catch2> > >,       tuple<lambda_functor<TryArg>, LF1, LF2>    > >try_catch(  const lambda_functor<TryArg>& a1,   const tagged_lambda_functor<detail::exception_catch_tag<detail::catch_block<Catch1> >, LF1>& a2,  const tagged_lambda_functor<detail::exception_catch_tag<Catch2>, LF2>& a3) {   return     lambda_functor_base<      action<3, try_catch_action<catch_action<detail::catch_block<Catch1>, Catch2> > >,       tuple<lambda_functor<TryArg>, LF1, LF2>    >     ( tuple<lambda_functor<TryArg>, LF1, LF2>(a1, a2, a3));}template <class TryArg, class Catch1, class LF1,                         class Catch2, class LF2,                         class Catch3, class LF3>inline const lambda_functor<   lambda_functor_base<     action<4, try_catch_action<catch_action<detail::catch_block<Catch1>, detail::catch_block<Catch2>, Catch3> > >,     tuple<lambda_functor<TryArg>, LF1, LF2, LF3>  > >try_catch(  const lambda_functor<TryArg>& a1,   const tagged_lambda_functor<detail::exception_catch_tag<detail::catch_block<Catch1> >, LF1>& a2,  const tagged_lambda_functor<detail::exception_catch_tag<detail::catch_block<Catch2> >, LF2>& a3,  const tagged_lambda_functor<detail::exception_catch_tag<Catch3>, LF3>& a4) {   return       lambda_functor_base<         action<4, try_catch_action<catch_action<detail::catch_block<Catch1>, detail::catch_block<Catch2>, Catch3> > >,         tuple<lambda_functor<TryArg>, LF1, LF2, LF3>      >     ( tuple<lambda_functor<TryArg>, LF1, LF2, LF3>(a1, a2, a3, a4));}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?