пятница, 21 октября 2016 г.

Template Magic

All remember compile-time factorial example


#include <iostream>

template<const int N> 
struct factorial {
    int num;
    factorial() {
        num = N * factorial<N-1>().num;
    }
};

template<>
struct factorial<0> 
{
    const int num = 1;
};

int main()
{
    factorial<5> t;
    std::cout << t.num << "\n";
    return 0;
}

Now we can use variadic template args like this


#include <iostream>

template<const int ...Args> struct factorial;

struct base { int num = 1; };

template<const int N, const int ...Args>
struct factorial<N, Args...> : base {
    factorial() {
        num = N * factorial<Args...>().num;
    }
};

template<> struct factorial<>  : base { };

int main()
{
    factorial<1,2,3,4,5> t;
    std::cout << t.num << "\n";
    return 0;
}

Moreover we could do better with inheritance


#include <iostream>

template<const int ...Args> 
struct factorial {
    const int num = 1;
};

template<const int N, const int ...Args>
struct factorial<N, Args...> : factorial<Args...> {
    typedef factorial<Args...> base_t;
    const int num = N * base_t::num;
};

template<> 
struct factorial<> {
    const int num = 1;
};

int main()
{
    factorial<1,2,3,4> t;
    std::cout << t.num << "\n";
    return 0;
}

Recursion via method run(). Conclusion in class with one template argument


#include <iostream>
#include <string>

template< typename ...ARGS > struct record;

template <typename FIELD, typename ...ARGS>
struct record< FIELD, ARGS... > : record<ARGS...> {
    typedef record<ARGS...> base_record_t;
    enum { index = base_record_t::index + 1 };
    
    void run() {
        base_record_t::run();
        std::cout << FIELD::name() << " " << index << "\n";
    }
};

template <typename FIELD>
struct record<FIELD> {
    enum { index = 0 };
    void run() {
        std::cout << FIELD::name() << " " << index << "\n";
    }    
};

struct f1 { static const char * name() { return "f1"; } };
struct f2 { static const char * name() { return "f2"; } };
struct f3 { static const char * name() { return "f3"; } };

int main()
{
    record<f1,f2,f3> r;
    r.run();
    return 0;
}