error.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. #ifndef BOOST_LEAF_ERROR_HPP_INCLUDED
  2. #define BOOST_LEAF_ERROR_HPP_INCLUDED
  3. // Copyright 2018-2022 Emil Dotchevski and Reverge Studios, Inc.
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/leaf/config.hpp>
  7. #include <boost/leaf/detail/optional.hpp>
  8. #include <boost/leaf/detail/demangle.hpp>
  9. #include <boost/leaf/detail/function_traits.hpp>
  10. #include <boost/leaf/detail/print.hpp>
  11. #include <type_traits>
  12. #include <iosfwd>
  13. #if BOOST_LEAF_CFG_DIAGNOSTICS
  14. # include <sstream>
  15. # include <string>
  16. # include <set>
  17. #endif
  18. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  19. # include <system_error>
  20. #endif
  21. #if BOOST_LEAF_CFG_CAPTURE
  22. # include <memory>
  23. #endif
  24. #define BOOST_LEAF_TOKEN_PASTE(x, y) x ## y
  25. #define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y)
  26. #define BOOST_LEAF_TMP BOOST_LEAF_TOKEN_PASTE2(boost_leaf_tmp_, __LINE__)
  27. #define BOOST_LEAF_ASSIGN(v,r)\
  28. auto && BOOST_LEAF_TMP = r;\
  29. static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
  30. "BOOST_LEAF_ASSIGN/BOOST_LEAF_AUTO requires a result object as the second argument (see is_result_type)");\
  31. if( !BOOST_LEAF_TMP )\
  32. return BOOST_LEAF_TMP.error();\
  33. v = std::forward<decltype(BOOST_LEAF_TMP)>(BOOST_LEAF_TMP).value()
  34. #define BOOST_LEAF_AUTO(v, r)\
  35. BOOST_LEAF_ASSIGN(auto v, r)
  36. #if BOOST_LEAF_CFG_GNUC_STMTEXPR
  37. #define BOOST_LEAF_CHECK(r)\
  38. ({\
  39. auto && BOOST_LEAF_TMP = (r);\
  40. static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
  41. "BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
  42. if( !BOOST_LEAF_TMP )\
  43. return BOOST_LEAF_TMP.error();\
  44. std::move(BOOST_LEAF_TMP);\
  45. }).value()
  46. #else
  47. #define BOOST_LEAF_CHECK(r)\
  48. {\
  49. auto && BOOST_LEAF_TMP = (r);\
  50. static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(BOOST_LEAF_TMP)>::type>::value,\
  51. "BOOST_LEAF_CHECK requires a result object (see is_result_type)");\
  52. if( !BOOST_LEAF_TMP )\
  53. return BOOST_LEAF_TMP.error();\
  54. }
  55. #endif
  56. #define BOOST_LEAF_NEW_ERROR ::boost::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error
  57. namespace boost { namespace leaf {
  58. class error_id;
  59. namespace leaf_detail
  60. {
  61. struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_unexpected_enabled_counter;
  62. struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_id_factory_current_id;
  63. struct inject_loc
  64. {
  65. char const * const file;
  66. int const line;
  67. char const * const fn;
  68. template <class T>
  69. friend T operator+( inject_loc loc, T && x ) noexcept
  70. {
  71. x.load_source_location_(loc.file, loc.line, loc.fn);
  72. return std::move(x);
  73. }
  74. };
  75. }
  76. } }
  77. ////////////////////////////////////////
  78. namespace boost { namespace leaf {
  79. #if BOOST_LEAF_CFG_DIAGNOSTICS
  80. namespace leaf_detail
  81. {
  82. class BOOST_LEAF_SYMBOL_VISIBLE e_unexpected_count
  83. {
  84. public:
  85. char const * (*first_type)();
  86. int count;
  87. BOOST_LEAF_CONSTEXPR explicit e_unexpected_count(char const * (*ft)()) noexcept:
  88. first_type(ft),
  89. count(1)
  90. {
  91. }
  92. template <class CharT, class Traits>
  93. void print( std::basic_ostream<CharT, Traits> & os ) const
  94. {
  95. BOOST_LEAF_ASSERT(first_type != nullptr);
  96. BOOST_LEAF_ASSERT(count>0);
  97. os << "Detected ";
  98. if( count==1 )
  99. os << "1 attempt to communicate an unexpected error object";
  100. else
  101. os << count << " attempts to communicate unexpected error objects, the first one";
  102. (os << " of type " << first_type() << '\n').flush();
  103. }
  104. };
  105. template <>
  106. struct diagnostic<e_unexpected_count, false, false>
  107. {
  108. static constexpr bool is_invisible = true;
  109. template <class CharT, class Traits>
  110. BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream<CharT, Traits> &, e_unexpected_count const &) noexcept { }
  111. };
  112. class BOOST_LEAF_SYMBOL_VISIBLE e_unexpected_info
  113. {
  114. std::string s_;
  115. std::set<char const *(*)()> already_;
  116. public:
  117. e_unexpected_info() noexcept
  118. {
  119. }
  120. template <class E>
  121. void add(E && e)
  122. {
  123. if( !diagnostic<E>::is_invisible && already_.insert(&type<E>).second )
  124. {
  125. std::stringstream s;
  126. diagnostic<E>::print(s,e);
  127. (s << '\n').flush();
  128. s_ += s.str();
  129. }
  130. }
  131. template <class CharT, class Traits>
  132. void print( std::basic_ostream<CharT, Traits> & os ) const
  133. {
  134. os << "Unhandled error objects:\n" << s_;
  135. }
  136. };
  137. template <>
  138. struct diagnostic<e_unexpected_info, false, false>
  139. {
  140. static constexpr bool is_invisible = true;
  141. template <class CharT, class Traits>
  142. BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream<CharT, Traits> &, e_unexpected_info const &) noexcept { }
  143. };
  144. }
  145. #endif
  146. } }
  147. ////////////////////////////////////////
  148. namespace boost { namespace leaf {
  149. struct BOOST_LEAF_SYMBOL_VISIBLE e_source_location
  150. {
  151. char const * file;
  152. int line;
  153. char const * function;
  154. template <class CharT, class Traits>
  155. friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, e_source_location const & x )
  156. {
  157. return os << leaf::type<e_source_location>() << ": " << x.file << '(' << x.line << ") in function " << x.function;
  158. }
  159. };
  160. ////////////////////////////////////////
  161. namespace leaf_detail
  162. {
  163. template <class E>
  164. class BOOST_LEAF_SYMBOL_VISIBLE slot:
  165. optional<E>
  166. {
  167. slot( slot const & ) = delete;
  168. slot & operator=( slot const & ) = delete;
  169. using impl = optional<E>;
  170. slot<E> * prev_;
  171. public:
  172. BOOST_LEAF_CONSTEXPR slot() noexcept:
  173. prev_(nullptr)
  174. {
  175. }
  176. BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept:
  177. optional<E>(std::move(x)),
  178. prev_(nullptr)
  179. {
  180. BOOST_LEAF_ASSERT(x.prev_==nullptr);
  181. }
  182. BOOST_LEAF_CONSTEXPR void activate() noexcept
  183. {
  184. prev_ = tls::read_ptr<slot<E>>();
  185. tls::write_ptr<slot<E>>(this);
  186. }
  187. BOOST_LEAF_CONSTEXPR void deactivate() noexcept
  188. {
  189. tls::write_ptr<slot<E>>(prev_);
  190. }
  191. BOOST_LEAF_CONSTEXPR void propagate( int err_id ) noexcept;
  192. template <class CharT, class Traits>
  193. void print( std::basic_ostream<CharT, Traits> & os, int key_to_print ) const
  194. {
  195. #if BOOST_LEAF_CFG_DIAGNOSTICS
  196. if( !diagnostic<E>::is_invisible )
  197. if( int k = this->key() )
  198. {
  199. if( key_to_print )
  200. {
  201. if( key_to_print!=k )
  202. return;
  203. }
  204. else
  205. os << '[' << k << ']';
  206. diagnostic<E>::print(os, value(k));
  207. (os << '\n').flush();
  208. }
  209. #else
  210. (void) os;
  211. (void) key_to_print;
  212. #endif
  213. }
  214. using impl::put;
  215. using impl::has_value;
  216. using impl::value;
  217. };
  218. #if BOOST_LEAF_CFG_DIAGNOSTICS
  219. template <class E>
  220. BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept
  221. {
  222. if( slot<e_unexpected_count> * sl = tls::read_ptr<slot<e_unexpected_count>>() )
  223. {
  224. if( e_unexpected_count * unx = sl->has_value(err_id) )
  225. ++unx->count;
  226. else
  227. sl->put(err_id, e_unexpected_count(&type<E>));
  228. }
  229. }
  230. template <class E>
  231. BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept
  232. {
  233. if( slot<e_unexpected_info> * sl = tls::read_ptr<slot<e_unexpected_info>>() )
  234. {
  235. if( e_unexpected_info * unx = sl->has_value(err_id) )
  236. unx->add(std::forward<E>(e));
  237. else
  238. sl->put(err_id, e_unexpected_info()).add(std::forward<E>(e));
  239. }
  240. }
  241. template <class E>
  242. BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept
  243. {
  244. load_unexpected_count<E>(err_id);
  245. load_unexpected_info(err_id, std::forward<E>(e));
  246. }
  247. #endif
  248. template <class E>
  249. BOOST_LEAF_CONSTEXPR inline void slot<E>::propagate( int err_id ) noexcept
  250. {
  251. if( this->key()!=err_id && err_id!=0 )
  252. return;
  253. if( impl * p = tls::read_ptr<slot<E>>() )
  254. *p = std::move(*this);
  255. #if BOOST_LEAF_CFG_DIAGNOSTICS
  256. else
  257. {
  258. int c = int(tls::read_uint<tls_tag_unexpected_enabled_counter>());
  259. BOOST_LEAF_ASSERT(c>=0);
  260. if( c )
  261. load_unexpected(err_id, std::move(*this).value(err_id));
  262. }
  263. #endif
  264. }
  265. template <class E>
  266. BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept
  267. {
  268. static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
  269. static_assert(!std::is_same<typename std::decay<E>::type, error_id>::value, "Error objects of type error_id are not allowed");
  270. using T = typename std::decay<E>::type;
  271. BOOST_LEAF_ASSERT((err_id&3)==1);
  272. if( slot<T> * p = tls::read_ptr<slot<T>>() )
  273. (void) p->put(err_id, std::forward<E>(e));
  274. #if BOOST_LEAF_CFG_DIAGNOSTICS
  275. else
  276. {
  277. int c = int(tls::read_uint<tls_tag_unexpected_enabled_counter>());
  278. BOOST_LEAF_ASSERT(c>=0);
  279. if( c )
  280. load_unexpected(err_id, std::forward<E>(e));
  281. }
  282. #endif
  283. return 0;
  284. }
  285. template <class F>
  286. BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept
  287. {
  288. static_assert(function_traits<F>::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference");
  289. using E = typename std::decay<fn_arg_type<F,0>>::type;
  290. static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
  291. BOOST_LEAF_ASSERT((err_id&3)==1);
  292. if( auto sl = tls::read_ptr<slot<E>>() )
  293. {
  294. if( auto v = sl->has_value(err_id) )
  295. (void) std::forward<F>(f)(*v);
  296. else
  297. (void) std::forward<F>(f)(sl->put(err_id,E()));
  298. }
  299. return 0;
  300. }
  301. }
  302. ////////////////////////////////////////
  303. namespace leaf_detail
  304. {
  305. template <class=void>
  306. struct BOOST_LEAF_SYMBOL_VISIBLE id_factory
  307. {
  308. static atomic_unsigned_int counter;
  309. BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept
  310. {
  311. auto id = (counter+=4);
  312. BOOST_LEAF_ASSERT((id&3)==1);
  313. return id;
  314. }
  315. };
  316. template <class T>
  317. atomic_unsigned_int id_factory<T>::counter(unsigned(-3));
  318. inline int current_id() noexcept
  319. {
  320. unsigned id = tls::read_uint<tls_tag_id_factory_current_id>();
  321. BOOST_LEAF_ASSERT(id==0 || (id&3)==1);
  322. return int(id);
  323. }
  324. inline int new_id() noexcept
  325. {
  326. unsigned id = id_factory<>::generate_next_id();
  327. tls::write_uint<tls_tag_id_factory_current_id>(id);
  328. return int(id);
  329. }
  330. }
  331. ////////////////////////////////////////
  332. namespace leaf_detail
  333. {
  334. template <class T, int Arity = function_traits<T>::arity>
  335. struct load_item
  336. {
  337. static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument");
  338. };
  339. template <class E>
  340. struct load_item<E, -1>
  341. {
  342. BOOST_LEAF_CONSTEXPR static int load_( int err_id, E && e ) noexcept
  343. {
  344. return load_slot(err_id, std::forward<E>(e));
  345. }
  346. };
  347. template <class F>
  348. struct load_item<F, 0>
  349. {
  350. BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept
  351. {
  352. return load_slot(err_id, std::forward<F>(f)());
  353. }
  354. };
  355. template <class F>
  356. struct load_item<F, 1>
  357. {
  358. BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept
  359. {
  360. return accumulate_slot(err_id, std::forward<F>(f));
  361. }
  362. };
  363. }
  364. ////////////////////////////////////////
  365. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  366. namespace leaf_detail
  367. {
  368. class leaf_category final: public std::error_category
  369. {
  370. bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; }
  371. bool equivalent( std::error_code const &, int ) const noexcept final override { return false; }
  372. char const * name() const noexcept final override { return "LEAF error"; }
  373. std::string message( int ) const final override { return name(); }
  374. public:
  375. ~leaf_category() noexcept final override { }
  376. };
  377. template <class=void>
  378. struct get_error_category
  379. {
  380. static leaf_category cat;
  381. };
  382. template <class T>
  383. leaf_category get_error_category<T>::cat;
  384. inline int import_error_code( std::error_code const & ec ) noexcept
  385. {
  386. if( int err_id = ec.value() )
  387. {
  388. std::error_category const & cat = get_error_category<>::cat;
  389. if( &ec.category()==&cat )
  390. {
  391. BOOST_LEAF_ASSERT((err_id&3)==1);
  392. return (err_id&~3)|1;
  393. }
  394. else
  395. {
  396. err_id = new_id();
  397. (void) load_slot(err_id, ec);
  398. return (err_id&~3)|1;
  399. }
  400. }
  401. else
  402. return 0;
  403. }
  404. }
  405. inline bool is_error_id( std::error_code const & ec ) noexcept
  406. {
  407. bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat);
  408. BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1));
  409. return res;
  410. }
  411. #endif
  412. ////////////////////////////////////////
  413. namespace leaf_detail
  414. {
  415. BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept;
  416. }
  417. class BOOST_LEAF_SYMBOL_VISIBLE error_id
  418. {
  419. friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept;
  420. int value_;
  421. BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept:
  422. value_(value)
  423. {
  424. BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1));
  425. }
  426. public:
  427. BOOST_LEAF_CONSTEXPR error_id() noexcept:
  428. value_(0)
  429. {
  430. }
  431. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  432. error_id( std::error_code const & ec ) noexcept:
  433. value_(leaf_detail::import_error_code(ec))
  434. {
  435. BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1));
  436. }
  437. template <class Enum>
  438. error_id( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept:
  439. value_(leaf_detail::import_error_code(e))
  440. {
  441. }
  442. std::error_code to_error_code() const noexcept
  443. {
  444. return std::error_code(value_, leaf_detail::get_error_category<>::cat);
  445. }
  446. #endif
  447. BOOST_LEAF_CONSTEXPR error_id load() const noexcept
  448. {
  449. return *this;
  450. }
  451. template <class... Item>
  452. BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept
  453. {
  454. if( int err_id = value() )
  455. {
  456. int const unused[ ] = { 42, leaf_detail::load_item<Item>::load_(err_id, std::forward<Item>(item))... };
  457. (void) unused;
  458. }
  459. return *this;
  460. }
  461. BOOST_LEAF_CONSTEXPR int value() const noexcept
  462. {
  463. if( int v = value_ )
  464. {
  465. BOOST_LEAF_ASSERT((v&3)==1);
  466. return (v&~3)|1;
  467. }
  468. else
  469. return 0;
  470. }
  471. BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept
  472. {
  473. return value_ != 0;
  474. }
  475. BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept
  476. {
  477. return a.value_ == b.value_;
  478. }
  479. BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept
  480. {
  481. return !(a == b);
  482. }
  483. BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept
  484. {
  485. return a.value_ < b.value_;
  486. }
  487. template <class CharT, class Traits>
  488. friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, error_id x )
  489. {
  490. return os << x.value_;
  491. }
  492. BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept
  493. {
  494. BOOST_LEAF_ASSERT(file&&*file);
  495. BOOST_LEAF_ASSERT(line>0);
  496. BOOST_LEAF_ASSERT(function&&*function);
  497. BOOST_LEAF_ASSERT(value_);
  498. (void) load(e_source_location {file,line,function});
  499. }
  500. };
  501. namespace leaf_detail
  502. {
  503. BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept
  504. {
  505. BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1);
  506. return error_id((err_id&~3)|1);
  507. }
  508. }
  509. inline error_id new_error() noexcept
  510. {
  511. return leaf_detail::make_error_id(leaf_detail::new_id());
  512. }
  513. template <class... Item>
  514. inline error_id new_error( Item && ... item ) noexcept
  515. {
  516. return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward<Item>(item)...);
  517. }
  518. inline error_id current_error() noexcept
  519. {
  520. return leaf_detail::make_error_id(leaf_detail::current_id());
  521. }
  522. ////////////////////////////////////////////
  523. class polymorphic_context
  524. {
  525. protected:
  526. polymorphic_context() noexcept = default;
  527. ~polymorphic_context() noexcept = default;
  528. public:
  529. virtual error_id propagate_captured_errors() noexcept = 0;
  530. virtual void activate() noexcept = 0;
  531. virtual void deactivate() noexcept = 0;
  532. virtual void propagate( error_id ) noexcept = 0;
  533. virtual bool is_active() const noexcept = 0;
  534. inline virtual void print( std::ostream & ) const { };
  535. error_id captured_id_;
  536. };
  537. #if BOOST_LEAF_CFG_CAPTURE
  538. using context_ptr = std::shared_ptr<polymorphic_context>;
  539. #endif
  540. ////////////////////////////////////////////
  541. template <class Ctx>
  542. class context_activator
  543. {
  544. context_activator( context_activator const & ) = delete;
  545. context_activator & operator=( context_activator const & ) = delete;
  546. #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
  547. int const uncaught_exceptions_;
  548. #endif
  549. Ctx * ctx_;
  550. public:
  551. explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept:
  552. #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
  553. uncaught_exceptions_(std::uncaught_exceptions()),
  554. #endif
  555. ctx_(ctx.is_active() ? nullptr : &ctx)
  556. {
  557. if( ctx_ )
  558. ctx_->activate();
  559. }
  560. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept:
  561. #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS
  562. uncaught_exceptions_(x.uncaught_exceptions_),
  563. #endif
  564. ctx_(x.ctx_)
  565. {
  566. x.ctx_ = nullptr;
  567. }
  568. BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept
  569. {
  570. if( ctx_ && ctx_->is_active() )
  571. ctx_->deactivate();
  572. }
  573. };
  574. template <class Ctx>
  575. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator<Ctx> activate_context(Ctx & ctx) noexcept
  576. {
  577. return context_activator<Ctx>(ctx);
  578. }
  579. ////////////////////////////////////////////
  580. template <class R>
  581. struct is_result_type: std::false_type
  582. {
  583. };
  584. template <class R>
  585. struct is_result_type<R const>: is_result_type<R>
  586. {
  587. };
  588. } }
  589. #endif