/*============================================================================= This file is part of FLINT. FLINT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. FLINT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FLINT; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =============================================================================*/ /****************************************************************************** Copyright (C) 2013 Tom Bachmann ******************************************************************************/ #ifndef CXX_MP_H #define CXX_MP_H namespace flint { namespace mp { ///////////////////////////////// // BASIC METAPROGRAMMING HELPERS ///////////////////////////////// // Most of these helpers *compute* something. In this case, they have a static // static const member "val" storing the result of the computation. The // arguments of the computation are template parameters, and are usually *not* // PODs, but instead themselves types with a static constant "val" member. // See value_of, true_ and false_ for how to pass in explicit values to your // computation. // Wrap the boolean value "v" into the static const member "val". template struct value_of { static const bool val = v; }; // Boolean inputs for computations. struct true_ : value_of { }; struct false_ : value_of { }; // Compute if two input *types* (not values!) are equal. template struct equal_types : false_ { }; template struct equal_types : true_ { }; // Compute logical negation of the input value. template struct not_ : value_of { }; // Compute logical and of the input values. template struct and_ : and_ > { }; template struct and_ : value_of { }; template struct and_v : and_ > { }; // Compute logical or of the input values. template struct or_ : or_ > { }; template struct or_ : value_of { }; // Compute V1 or V2, depending on C template struct if_v {typedef V1 type;}; template struct if_v {typedef V2 type;}; template struct if_ : if_v { }; // Choose a value depending on a sequence of conditions. // This has he same meaning as // int select(bool c1 = false, bool c2 = false, bool c3 = false) // { // if(c1) // return v1; // if(c2) // return v2; // if(c3) // return v3; // return d; // } template struct select : if_::type> { }; template struct select {typedef D type;}; // Conditional template enabling helper. (See below for explanation.) template struct enable_if_v { typedef U type; static const int val = 0; }; template struct enable_if_v { }; // Conditional template enabling. // // These two helpers (enable_if and disable_if) can be used wherever the // SFINAE rule applies to conditionally enable or disable template // specialisations. // // If T evaluaties to true, then enable_if has a member typedef "type", which // is the parameter U, and also a static const int member val (of zero). // If on the other hand T evaluates to false, then enable_if is empty. // The meaning of T is reversed for disable_if. // See e.g. [0] or the tests for how to use this. // // [0] http://www.boost.org/doc/libs/1_53_0/libs/utility/enable_if.html // template struct enable_if : public enable_if_v { }; template struct disable_if : public enable_if, U> { }; struct empty { }; } // mp } // flint #endif