1 /* Metaprogramming utilities. 2 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> 3 Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com) 4 5 This file is part of the Parma Polyhedra Library (PPL). 6 7 The PPL is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by the 9 Free Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 The PPL is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software Foundation, 19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. 20 21 For the most up-to-date information see the Parma Polyhedra Library 22 site: http://bugseng.com/products/ppl/ . */ 23 24 #ifndef PPL_meta_programming_hh 25 #define PPL_meta_programming_hh 1 26 27 #include <gmpxx.h> 28 29 namespace Parma_Polyhedra_Library { 30 31 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 32 /*! \brief 33 Declares a per-class constant of type <CODE>bool</CODE>, called \p name 34 and with value \p value. 35 36 \ingroup PPL_CXX_interface 37 Differently from static constants, \p name needs not (and cannot) be 38 defined (for static constants, the need for a further definition is 39 mandated by Section 9.4.2/4 of the C++ standard). 40 */ 41 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 42 #define const_bool_nodef(name, value) \ 43 enum const_bool_value_ ## name { PPL_U(name) = (value) } 44 45 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 46 /*! \brief 47 Declares a per-class constant of type <CODE>int</CODE>, called \p name 48 and with value \p value. 49 50 \ingroup PPL_CXX_interface 51 Differently from static constants, \p name needs not (and cannot) be 52 defined (for static constants, the need for a further definition is 53 mandated by Section 9.4.2/4 of the C++ standard). 54 */ 55 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 56 #define const_int_nodef(name, value) \ 57 enum anonymous_enum_ ## name { PPL_U(name) = (value) } 58 59 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 60 /*! \brief 61 Declares a per-class constant of type \p type, called \p name 62 and with value \p value. The value of the constant is accessible 63 by means of the syntax <CODE>name()</CODE>. 64 65 \ingroup PPL_CXX_interface 66 Differently from static constants, \p name needs not (and cannot) be 67 defined (for static constants, the need for a further definition is 68 mandated by Section 9.4.2/4 of the C++ standard). 69 */ 70 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 71 #define const_value_nodef(type, name, value) \ 72 static type PPL_U(name)() { \ 73 return (value); \ 74 } 75 76 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 77 /*! \brief 78 Declares a per-class constant of type \p type, called \p name 79 and with value \p value. A constant reference to the constant 80 is accessible by means of the syntax <CODE>name()</CODE>. 81 82 \ingroup PPL_CXX_interface 83 Differently from static constants, \p name needs not (and cannot) be 84 defined (for static constants, the need for a further definition is 85 mandated by Section 9.4.2/4 of the C++ standard). 86 */ 87 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 88 #define const_ref_nodef(type, name, value) \ 89 static const type& PPL_U(name)() { \ 90 static type PPL_U(name) = (value); \ 91 return (name); \ 92 } 93 94 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 95 /*! \brief 96 A class that is only defined if \p b evaluates to <CODE>true</CODE>. 97 98 \ingroup PPL_CXX_interface 99 This is the non-specialized case, so the class is declared but not defined. 100 */ 101 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 102 template <bool b> 103 struct Compile_Time_Check; 104 105 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 106 /*! \brief 107 A class that is only defined if \p b evaluates to <CODE>true</CODE>. 108 109 \ingroup PPL_CXX_interface 110 This is the specialized case with \p b equal to <CODE>true</CODE>, 111 so the class is declared and (trivially) defined. 112 */ 113 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 114 template <> 115 struct Compile_Time_Check<true> { 116 }; 117 118 #define PPL_COMPILE_TIME_CHECK_NAME(suffix) compile_time_check_ ## suffix 119 #define PPL_COMPILE_TIME_CHECK_AUX(e, suffix) \ 120 enum anonymous_enum_compile_time_check_ ## suffix { \ 121 /* If e evaluates to false, then the sizeof cannot be compiled. */ \ 122 PPL_COMPILE_TIME_CHECK_NAME(suffix) \ 123 = sizeof(Parma_Polyhedra_Library::Compile_Time_Check<(e)>) \ 124 } 125 126 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 127 /*! \brief 128 Produces a compilation error if the compile-time constant \p e does 129 not evaluate to <CODE>true</CODE> 130 \ingroup PPL_CXX_interface 131 */ 132 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 133 #define PPL_COMPILE_TIME_CHECK(e, msg) PPL_COMPILE_TIME_CHECK_AUX(e, __LINE__) 134 135 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 136 /*! \brief 137 A class holding a constant called <CODE>value</CODE> that evaluates 138 to \p b. 139 \ingroup PPL_CXX_interface 140 */ 141 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 142 template <bool b> 143 struct Bool { 144 enum const_bool_value { 145 value = b 146 }; 147 }; 148 149 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 150 /*! \brief 151 A class holding a constant called <CODE>value</CODE> that evaluates 152 to <CODE>true</CODE>. 153 \ingroup PPL_CXX_interface 154 */ 155 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 156 struct True : public Bool<true> { 157 }; 158 159 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 160 /*! \brief 161 A class holding a constant called <CODE>value</CODE> that evaluates 162 to <CODE>false</CODE>. 163 \ingroup PPL_CXX_interface 164 */ 165 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 166 struct False : public Bool<false> { 167 }; 168 169 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 170 /*! \brief 171 A class holding a constant called <CODE>value</CODE> that evaluates 172 to <CODE>true</CODE> if and only if \p T1 is the same type as \p T2. 173 174 \ingroup PPL_CXX_interface 175 This is the non-specialized case, in which \p T1 and \p T2 can be different. 176 */ 177 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 178 template <typename T1, typename T2> 179 struct Is_Same : public False { 180 }; 181 182 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 183 /*! \brief 184 A class holding a constant called <CODE>value</CODE> that evaluates 185 to <CODE>true</CODE> if and only if \p T1 is the same type as \p T2. 186 187 \ingroup PPL_CXX_interface 188 This is the specialization in which \p T1 and \p T2 are equal. 189 */ 190 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 191 template <typename T> 192 struct Is_Same<T, T> : public True { 193 }; 194 195 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 196 /*! \brief 197 A class holding a constant called <CODE>value</CODE> that evaluates 198 to <CODE>true</CODE> if and only if \p Base is the same type as \p Derived 199 or \p Derived is a class derived from \p Base. 200 201 \ingroup PPL_CXX_interface 202 \note 203 Care must be taken to use this predicate with template classes. 204 Suppose we have 205 \code 206 template <typename T> struct B; 207 template <typename T> struct D : public B<T>; 208 \endcode 209 Of course, we cannot test if, for some type variable <CODE>U</CODE>, we have 210 <CODE>Is_Same_Or_Derived<B<U>, Type>:: const_bool_value:: value == true</CODE>. 211 But we can do as follows: 212 \code 213 struct B_Base { 214 }; 215 216 template <typename T> struct B : public B_Base; 217 \endcode 218 This enables us to inquire 219 <CODE>Is_Same_Or_Derived<B_Base, Type>:: const_bool_value:: value</CODE>. 220 */ 221 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 222 template <typename Base, typename Derived> 223 struct Is_Same_Or_Derived { 224 225 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 226 //! A class that is constructible from just anything. 227 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 228 struct Any { 229 //! The universal constructor. 230 template <typename T> 231 Any(const T&); 232 }; 233 234 //! Overloading with \p Base. 235 static char func(const Base&); 236 237 //! Overloading with \p Any. 238 static double func(Any); 239 240 //! A function obtaining a const reference to a \p Derived object. 241 static const Derived& derived_object(); 242 243 PPL_COMPILE_TIME_CHECK(sizeof(char) != sizeof(double), 244 "architecture with sizeof(char) == sizeof(double)" 245 " (!?)"); 246 247 enum const_bool_value { 248 /*! 249 Assuming <CODE>sizeof(char) != sizeof(double)</CODE>, the C++ 250 overload resolution mechanism guarantees that <CODE>value</CODE> 251 evaluates to <CODE>true</CODE> if and only if <CODE>Base</CODE> 252 is the same type as <CODE>Derived</CODE> or <CODE>Derived</CODE> 253 is a class derived from <CODE>Base</CODE>. 254 */ 255 value = (sizeof(func(derived_object())) == sizeof(char)) 256 }; 257 }; 258 259 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 260 /*! \brief 261 A class that provides a type member called <CODE>type</CODE> equivalent 262 to \p T if and only if \p b is <CODE>true</CODE>. 263 264 \ingroup PPL_CXX_interface 265 This is the non-specialized case, in which the <CODE>type</CODE> member 266 is not present. 267 */ 268 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 269 template <bool b, typename T = void> 270 struct Enable_If { 271 }; 272 273 template <typename Type, Type, typename T = void> 274 struct Enable_If_Is { 275 typedef T type; 276 }; 277 278 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS 279 /*! \brief 280 A class that provides a type member called <CODE>type</CODE> equivalent 281 to \p T if and only if \p b is <CODE>true</CODE>. 282 283 \ingroup PPL_CXX_interface 284 This is the specialization in which the <CODE>type</CODE> member 285 is present. 286 287 \note 288 Let <CODE>T</CODE>, <CODE>T1</CODE> and <CODE>T2</CODE> be any type 289 expressions and suppose we have some template function 290 <CODE>T f(T1, T2)</CODE>. If we want to declare a specialization 291 that is enabled only if some compile-time checkable condition holds, 292 we simply declare the specialization by 293 \code 294 template ... 295 typename Enable_If<condition, T>::type 296 foo(T1 x, T2 y); 297 \endcode 298 For all the instantiations of the template parameters that cause 299 <CODE>condition</CODE> to evaluate to <CODE>false</CODE>, 300 the <CODE>Enable_If<condition, T>::type</CODE> member will not be defined. 301 Hence, for that instantiations, the specialization will not be eligible. 302 */ 303 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS) 304 template <typename T> 305 struct Enable_If<true, T> { 306 typedef T type; 307 }; 308 309 template <typename T> 310 struct Is_Native : public False { 311 }; 312 313 template <> struct Is_Native<char> : public True { }; 314 template <> struct Is_Native<signed char> : public True { }; 315 template <> struct Is_Native<signed short> : public True { }; 316 template <> struct Is_Native<signed int> : public True { }; 317 template <> struct Is_Native<signed long> : public True { }; 318 template <> struct Is_Native<signed long long> : public True { }; 319 template <> struct Is_Native<unsigned char> : public True { }; 320 template <> struct Is_Native<unsigned short> : public True { }; 321 template <> struct Is_Native<unsigned int> : public True { }; 322 template <> struct Is_Native<unsigned long> : public True { }; 323 template <> struct Is_Native<unsigned long long> : public True { }; 324 325 #if PPL_SUPPORTED_FLOAT 326 template <> struct Is_Native<float> : public True { }; 327 #endif 328 #if PPL_SUPPORTED_DOUBLE 329 template <> struct Is_Native<double> : public True { }; 330 #endif 331 #if PPL_SUPPORTED_LONG_DOUBLE 332 template <> struct Is_Native<long double> : public True { }; 333 #endif 334 335 template <> struct Is_Native<mpz_class> : public True { }; 336 337 template <> struct Is_Native<mpq_class> : public True { }; 338 339 } // namespace Parma_Polyhedra_Library 340 341 #endif // !defined(PPL_meta_programming_hh) 342