Metaprogramming templates ( template metaprogramming ( TMP )) is the process of writing template-based C ++ programs that are executed at compile time. Think about it for a minute: a template metaprogram is a program written in C ++ that runs inside the C ++ compiler ...
It has been proven that TMP technology provides a complete Turing machine , that is, it has enough power for any calculations ...
template<int n, int d> struct Fractional { enum { N = n, D = d }; };
template<int n, int d> struct Fractional { private: enum { NonZeroDenominator = n / d }; public: enum { N = n, D = d }; };
typedef Fractional<9, 0> number; // ... int temp = number::D;
error C2057: expected constant expression
is not clear, but if we go to the place of the error, we’ll just see the NonZeroDenominator
variable - at least something ... int gcd(int a, int b) { if(b == 0) return a; return gcd(b, a % b); }
template<int n1, int n2> struct GCD { enum { value = GCD<n2, n1 % n2>::value }; }; template<int n1> struct GCD<n1, 0> { enum { value = n1 }; };
template<int n, int d> struct Fractional { private: enum { NonZeroDenominator = n / d }; enum { gcd = GCD<n, d>::value }; public: enum { N = n / gcd, D = d / gcd }; };
// // Divide // template<typename n, typename d> struct Divide { }; template<int n1, int d1, int n2, int d2> struct Divide<Fractional<n1, d1>, Fractional<n2, d2> > { private: typedef Fractional<n1, d1> n; typedef Fractional<n2, d2> d; public: typedef Fractional<n::N * d::D, n::D * d::N> value; }; // // Multiple // template<typename n, typename d> struct Multiple { }; template<int n1, int d1, int n2, int d2> struct Multiple<Fractional<n1, d1>, Fractional<n2, d2> > { private: typedef Fractional<n1, d1> n; typedef Fractional<n2, d2> d; public: typedef Fractional<n::N * d::N, n::D * d::D> value; }; // // Substract // template<typename n, typename d> struct Substract { }; template<int n1, int d1, int n2, int d2> struct Substract<Fractional<n1, d1>, Fractional<n2, d2> > { private: typedef Fractional<n1, d1> n; typedef Fractional<n2, d2> d; public: typedef Fractional<n::N * d::D - d::N * n::D, n::D * d::D> value; }; // // Add // template<typename n, typename d> struct Add { }; template<int n1, int d1, int n2, int d2> struct Add<Fractional<n1, d1>, Fractional<n2, d2> > { private: typedef Fractional<n1, d1> n; typedef Fractional<n2, d2> d; public: typedef Fractional<n::N * d::D + d::N * n::D, n::D * d::D> value; };
Divide
- noting that it (the function) takes 2 arguments. And further, with the help of a partial template specialization, we specify that we want to see not something, but the template ID we need, i.e. Divide<n1, n2>
, for example. Use : typedef Fractional<4, 20> n1; typedef Fractional<5, 32> n2; typedef Add<n1, n2>::value summ; printf("%i/%i\n", summ::N, summ::D); // 57/160
// // Factorial // template<int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; }; template<> struct Factorial<0> { enum { value = 1 }; }; // // Power // template<int x, int n> struct Pow { enum { value = x * Pow<x, n - 1>::value }; }; template<int x> struct Pow<x, 0> { enum { value = 1 }; };
Exp<4, 8>::value
will give a fractional number, which is numerically equal to the exponent to the 4th degree and summation is made only to 8 (infinity near) member inclusive. // // Exponent // template<int x, int n> struct Exp : public Exp<x, n - 1> { private: typedef typename Exp<x, n - 1>::value previous; protected: typedef Fractional<Pow<x, n>::value, Factorial<n>::value> current; public: typedef typename Add<current, previous>::value value; }; template<int x> struct Exp<x, 0> { public: typedef Fractional<Pow<x, 0>::value, Factorial<0>::value> current; public: typedef current value; };
current
contains the value of one member of the series - i.e. one class in this whole class hierarchy, roughly speaking, is intended to store the value of one member . And with the help of the fact that he can take the data of the base class - that is the value of the previous member of the series - then all this gives us that, apart from the value of one separate element of the series, we in the current class have the sum of the series up to this element (class) inclusive. int main() { // typedef Exp<1, 8>::value result; printf("%i/%i\n", result::N, result::D); // printf("%f\n", result::N / static_cast<float>(result::D)); }
int
overflow.Source: https://habr.com/ru/post/168961/
All Articles