1 /* 2 Copyright (C) 2013 Tom Bachmann 3 4 This file is part of FLINT. 5 6 FLINT is free software: you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License (LGPL) as published 8 by the Free Software Foundation; either version 2.1 of the License, or 9 (at your option) any later version. See <http://www.gnu.org/licenses/>. 10 */ 11 12 #ifndef CXX_MP_H 13 #define CXX_MP_H 14 15 namespace flint { 16 namespace mp { 17 ///////////////////////////////// 18 // BASIC METAPROGRAMMING HELPERS 19 ///////////////////////////////// 20 // Most of these helpers *compute* something. In this case, they have a static 21 // static const member "val" storing the result of the computation. The 22 // arguments of the computation are template parameters, and are usually *not* 23 // PODs, but instead themselves types with a static constant "val" member. 24 // See value_of, true_ and false_ for how to pass in explicit values to your 25 // computation. 26 27 // Wrap the boolean value "v" into the static const member "val". 28 template<bool v> struct value_of { static const bool val = v; }; 29 30 // Boolean inputs for computations. 31 struct true_ : value_of<true> { }; 32 struct false_ : value_of<false> { }; 33 34 // Compute if two input *types* (not values!) are equal. 35 template<class T, class U> 36 struct equal_types : false_ { }; 37 template<class T> 38 struct equal_types<T, T> : true_ { }; 39 40 // Compute logical negation of the input value. 41 template<class T> 42 struct not_ : value_of<!T::val> { }; 43 44 // Compute logical and of the input values. 45 template<class T1, class T2, class T3 = void, 46 class T4 = void, class T5 = void, class T6 = void, class T7 = void, class T8 = void> 47 struct and_ : and_<T1, and_<T2, T3, T4, T5, T6, T7, T8> > { }; 48 49 template<class T, class U> 50 struct and_<T, U, void, void, void, void> : value_of<T::val && U::val> { }; 51 52 template<class T, bool u> 53 struct and_v : and_<T, value_of<u> > { }; 54 55 // Compute logical or of the input values. 56 template<class T1, class T2, class T3 = void, 57 class T4 = void, class T5 = void, class T6 = void> 58 struct or_ : or_<T1, or_<T2, T3, T4, T5> > { }; 59 60 template<class T, class U> 61 struct or_<T, U, void, void, void, void> : value_of<T::val || U::val> { }; 62 63 // Compute V1 or V2, depending on C 64 template<bool C, class V1, class V2> 65 struct if_v {typedef V1 type;}; 66 template<class V1, class V2> 67 struct if_v<false, V1, V2> {typedef V2 type;}; 68 69 template<class C, class V1, class V2> 70 struct if_ : if_v<C::val, V1, V2> { }; 71 72 // Choose a value depending on a sequence of conditions. 73 // This has he same meaning as 74 // int select(bool c1 = false, bool c2 = false, bool c3 = false) 75 // { 76 // if(c1) 77 // return v1; 78 // if(c2) 79 // return v2; 80 // if(c3) 81 // return v3; 82 // return d; 83 // } 84 template<class D, class C1 = void, class V1 = void, 85 class C2 = void, class V2 = void, 86 class C3 = void, class V3 = void> 87 struct select : if_<C1, V1, typename select<D, C2, V2, C3, V3>::type> { }; 88 89 template<class D> 90 struct select<D, void, void, void, void, void, void> {typedef D type;}; 91 92 // Conditional template enabling helper. (See below for explanation.) 93 template<bool, class U = void> 94 struct enable_if_v 95 { 96 typedef U type; 97 static const int val = 0; 98 }; 99 template<class U> 100 struct enable_if_v<false, U> { }; 101 102 // Conditional template enabling. 103 // 104 // These two helpers (enable_if and disable_if) can be used wherever the 105 // SFINAE rule applies to conditionally enable or disable template 106 // specialisations. 107 // 108 // If T evaluaties to true, then enable_if has a member typedef "type", which 109 // is the parameter U, and also a static const int member val (of zero). 110 // If on the other hand T evaluates to false, then enable_if is empty. 111 // The meaning of T is reversed for disable_if. 112 // See e.g. [0] or the tests for how to use this. 113 // 114 // [0] http://www.boost.org/doc/libs/1_53_0/libs/utility/enable_if.html 115 // 116 template<class T, class U = void> 117 struct enable_if : public enable_if_v<T::val, U> { }; 118 template<class T, class U = void> 119 struct disable_if : public enable_if<not_<T>, U> { }; 120 121 struct empty { }; 122 } // mp 123 } // flint 124 125 #endif 126