exception_wrapper: now without undefined behavior
[folly.git] / folly / ExceptionWrapper.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_EXCEPTIONWRAPPER_H
18 #define FOLLY_EXCEPTIONWRAPPER_H
19
20 #include <cassert>
21 #include <exception>
22 #include <memory>
23 #include "folly/detail/ExceptionWrapper.h"
24
25 namespace folly {
26
27 class exception_wrapper {
28  public:
29   exception_wrapper() : throwfn_(nullptr) { }
30
31   void throwException() {
32     if (throwfn_) {
33       throwfn_(item_.get());
34     }
35   }
36
37   std::exception* get() { return item_.get(); }
38   const std::exception* get() const { return item_.get(); }
39
40   std::exception* operator->() { return get(); }
41   const std::exception* operator->() const { return get(); }
42
43   std::exception& operator*() { assert(get()); return *get(); }
44   const std::exception& operator*() const { assert(get()); return *get(); }
45
46   explicit operator bool() const { return get(); }
47
48  private:
49   std::shared_ptr<std::exception> item_;
50   void (*throwfn_)(std::exception*);
51
52   template <class T, class... Args>
53   friend exception_wrapper make_exception_wrapper(Args&&... args);
54 };
55
56 template <class T, class... Args>
57 exception_wrapper make_exception_wrapper(Args&&... args) {
58   exception_wrapper ew;
59   ew.item_ = std::make_shared<T>(std::forward<Args>(args)...);
60   ew.throwfn_ = folly::detail::Thrower<T>::doThrow;
61   return ew;
62 }
63
64 }
65 #endif