pqc/external/flint-2.4.3/flintxx/mp.h
2014-05-24 23:16:06 +02:00

140 lines
4.7 KiB
C++

/*=============================================================================
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<bool v> struct value_of { static const bool val = v; };
// Boolean inputs for computations.
struct true_ : value_of<true> { };
struct false_ : value_of<false> { };
// Compute if two input *types* (not values!) are equal.
template<class T, class U>
struct equal_types : false_ { };
template<class T>
struct equal_types<T, T> : true_ { };
// Compute logical negation of the input value.
template<class T>
struct not_ : value_of<!T::val> { };
// Compute logical and of the input values.
template<class T1, class T2, class T3 = void,
class T4 = void, class T5 = void, class T6 = void, class T7 = void, class T8 = void>
struct and_ : and_<T1, and_<T2, T3, T4, T5, T6, T7, T8> > { };
template<class T, class U>
struct and_<T, U, void, void, void, void> : value_of<T::val && U::val> { };
template<class T, bool u>
struct and_v : and_<T, value_of<u> > { };
// Compute logical or of the input values.
template<class T1, class T2, class T3 = void,
class T4 = void, class T5 = void, class T6 = void>
struct or_ : or_<T1, or_<T2, T3, T4, T5> > { };
template<class T, class U>
struct or_<T, U, void, void, void, void> : value_of<T::val || U::val> { };
// Compute V1 or V2, depending on C
template<bool C, class V1, class V2>
struct if_v {typedef V1 type;};
template<class V1, class V2>
struct if_v<false, V1, V2> {typedef V2 type;};
template<class C, class V1, class V2>
struct if_ : if_v<C::val, V1, V2> { };
// 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<class D, class C1 = void, class V1 = void,
class C2 = void, class V2 = void,
class C3 = void, class V3 = void>
struct select : if_<C1, V1, typename select<D, C2, V2, C3, V3>::type> { };
template<class D>
struct select<D, void, void, void, void, void, void> {typedef D type;};
// Conditional template enabling helper. (See below for explanation.)
template<bool, class U = void>
struct enable_if_v
{
typedef U type;
static const int val = 0;
};
template<class U>
struct enable_if_v<false, U> { };
// 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<class T, class U = void>
struct enable_if : public enable_if_v<T::val, U> { };
template<class T, class U = void>
struct disable_if : public enable_if<not_<T>, U> { };
struct empty { };
} // mp
} // flint
#endif