spot  2.3.4
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
casts.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2011, 2015-2017 Laboratoire de Recherche et Développement
3 // de l'Epita (LRDE).
4 //
5 // This file is part of Spot, a model checking library.
6 //
7 // Spot is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Spot is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20 #pragma once
21 
22 #include <memory>
23 #include <type_traits>
24 
25 // We usually write code like
26 // subtypename* i = down_cast<subtypename*>(m);
27 // ... use i ...
28 // When NDEBUG is set, the down_cast is a fast static_cast.
29 // Otherwise, the down_cast is a dynamic_cast and may return 0
30 // on error, which is caught by an assert in the down_cast function.
31 //
32 // NB: It is valid to use down_cast with non-pointer template argument:
33 // subtypename& i = down_cast<subtypename&>(m);
34 // If an error occurs during the cast, an exception is thrown.
35 //
36 // NB: down_cast can also be used on shared_ptr.
37 
38 namespace
39 {
40  // A helper struct to check that downcasts are performed down an inheritance
41  // hierarchy, not between unrelated types.
42  template<typename Base, typename Derived>
43  struct is_base_of : std::is_base_of<Base, Derived>
44  {};
45  template<typename Base, typename Derived>
46  struct is_base_of<Base*, Derived*> : is_base_of<Base, Derived>
47  {};
48  // Also handle smart pointers.
49  template<typename Base, typename Derived>
50  struct is_base_of<std::shared_ptr<Base>, std::shared_ptr<Derived>>
51  : is_base_of<Base, Derived>
52  {};
53 
54  // std::is_pointer does not detect smart pointers.
55  // Make our own version that detects pointer, plain or smart.
56  template<typename T>
57  struct is_pointer : std::is_pointer<T>
58  {};
59  template<typename T>
60  struct is_pointer<std::shared_ptr<T>> : std::true_type
61  {};
62 
63  template<typename T, typename U, bool check>
64  struct _downcast;
65 
66  // A down-cast on non-pointer type is legitimate, e.g. down_cast<Derived&>(m);
67  // An error in the dynamic_cast will throw an exception.
68  template<typename T, typename U>
69  struct _downcast<T, U, false>
70  {
71  static_assert(is_base_of<U, T>::value, "invalid downcast");
72 
73  static
74  inline
75  T
76  cast(U u)
77 #ifdef NDEBUG
78  noexcept
79 #else
80  noexcept(is_pointer<T>::value)
81 #endif
82  {
83 #ifdef NDEBUG
84  return static_cast<T>(u);
85 #else
86  return dynamic_cast<T>(u);
87 #endif
88  }
89  };
90 
91  // A specialization for smart pointer, so that down_cast can be used
92  // uniformly.
93  // NB: Use
94  // auto d = down_cast<std::shared_ptr<T>>(b);
95  // instead of
96  // auto d = std::dynamic_pointer_cast<T>(b);
97  template<typename T, typename U>
98  struct _downcast<std::shared_ptr<T>, U, false>
99  {
100  static_assert(is_base_of<U, std::shared_ptr<T>>::value, "invalid downcast");
101 
102  static
103  inline
104  std::shared_ptr<T>
105  cast(U u) noexcept
106  {
107 #ifdef NDEBUG
108  return std::static_pointer_cast<T>(u);
109 #else
110  return std::dynamic_pointer_cast<T>(u);
111 #endif
112  }
113  };
114 
115  // Pointer type specialization.
116  // Cast errors are caught by an assertion, no exception is thrown.
117  template<typename T, typename U>
118  struct _downcast<T, U, true>
119  {
120  static
121  inline
122  T
123  cast(U u) noexcept
124  {
125  T t = _downcast<T, U, false>::cast(u);
126  SPOT_ASSERT(t);
127  return t;
128  }
129  };
130 } // anonymous namespace
131 
132 // The actual function to call.
133 template<typename T, typename U>
134 inline
135 T
136 down_cast(U u)
137 #ifdef NDEBUG
138  noexcept
139 #else
140  noexcept(is_pointer<T>::value)
141 #endif
142 {
143  return _downcast<T, U, is_pointer<T>::value>::cast(u);
144 }
145 
Definition: formula.hh:1671

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Thu May 11 2017 08:27:31 for spot by doxygen 1.8.8