Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant template specialization

Tags:

c++

templates

Is there an elegant way to specialize a template based on one of its template parameters?

Ie.

template<int N> struct Junk {
    static int foo() {
        // stuff
        return Junk<N - 1>::foo();
    }
};

// compile error: template argument '(size * 5)' involves template parameter(s)
template<int N> struct Junk<N*5> {
    static int foo() {
        // stuff
        return N;
    }
};

template<> struct Junk<0> {
    static int foo() {
        // stuff
        return 0;
    }
};

Ie. I am trying to specialize a template based on the parameter being divisible by 5. The only way I can seem to do it is like below:

template<int N> struct JunkDivisibleBy5 {
    static int foo() {
        // stuff
        return N;
    }
};

template<int N> struct Junk {
    static int foo() {
        // stuff
        if ((N - 1) % 5 == 0 && N != 1)
            return JunkDivisibleBy5<N - 1>::foo();
        else
            return Junk<N - 1>::foo();
    }
};


template<> struct Junk<0> {
    static int foo() {
        // stuff
        return 0;
    }
};

But this is significantly less elegant, and also necessitates instantiation of all templates even if the template argument shouldn't require it.

like image 536
Greg Rogers Avatar asked Nov 28 '22 08:11

Greg Rogers


2 Answers

How's this:

#include <iostream>
using namespace std;

template < typename T, T N, T D >
struct fraction {
    typedef T value_type;
    static const value_type num = N;
    static const value_type denom = D;
    static const bool is_div = (num % denom == 0);
};

template< typename T, T N, T D, bool P >
struct do_if {
    static void op() { cout << N << " NOT divisible by " << D << endl; }
};

template< typename T, T N, T D >
struct do_if< T, N, D, true > {
    static void op() { cout << N << " divisible by " << D << endl; }
};

template < int N >
void foo() {
    typedef fraction< int, N, 5 > f;
    do_if< typename f::value_type, f::num, f::denom, f::is_div >::op();
}

int main() {
    foo< -5 >();
    foo< -1 >();
    foo< 0 >();
    foo< 1 >();
    foo< 5 >();
    foo< 10000005 >();
    return 0;
}
like image 197
jwfearn Avatar answered Dec 21 '22 09:12

jwfearn


Using D programming language templates, one could write it as:

struct Junk(int N)
{
    static int foo()
    {
        static if (N == 0)
            return 0;
        else static if ((N % 5) == 0)
            return N;
        else
            return Junk!(N - 1).foo();
    }
}

static if's are executed at compile time.

like image 25
Walter Bright Avatar answered Dec 21 '22 09:12

Walter Bright