6

I have struct Opers with some arithmetic operations: mult(), div(), mod().

And I need to specialize template for certain values of n. Here is example for Opers<1>.

But, also I want to do specialization for n that are powers of 2 ( n = 2,4,8,16, ...) – in this case I can optimize operations mult() and div() (using bitwise shift left or right).

#include <iostream>
using namespace std;
template<int n> struct Opers {
    int mult(int x){
        return n*x;
    }
    int div(int x){
        return x / n;
    }   
    int mod(int x){
        return x % n;
    }   
};
template<> struct Opers<1> {
    int mult(int x){
        return 1;
    }
    int div(int x){
        return x;
    }   
    int mod(int x){
        return 0;
    }           
};
int main() {
    Opers<1> el2;
    cout << el2.mult(3) <<endl;
} 

I'm looking for construction like

template<> struct Opers<isPowerOfTwo()>
    int mult(int x){
        // do smth
     }

Is it possible or what manual should I read?

UPD. Using C++11 is allowed, and even would be better.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
takka
  • 63
  • 5
  • 5
    Ahh... optimize by using shifts. The compiler will be like, "whoa, I would *never* have thought of that"... – Kerrek SB Jun 02 '13 at 13:48
  • I know that it doesn't matter for compiler! It's just an example (connected with my study task), and I can't find right construction or approach to code that... – takka Jun 02 '13 at 13:53

2 Answers2

6

In C++11, you could do it this way. First of all, change your primary template so that it accepts a second, dummy parameter:

template<int n, typename = void>
struct Opers 
{
    // ...
};

Then, write a constexpr function that determines whether an integer is a power of 2:

constexpr bool is_power_of_two(int x)
{
    return (x == 1) || ((x % 2 == 0) && is_power_of_two(x / 2));
}

Finally, use SFINAE to enable or disable the specialization based on the result of your constexpr function:

#include <type_traits>

template<int n>
struct Opers<n, typename std::enable_if<is_power_of_two(n)>::type>
{
    // ...
};
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
3
template <int N, typename = void>
struct Operations
{
    // ....
};

template <int N, typename = std::enable_if<(N & (N - 1))>::type>
struct Operations
{
    // ....
};
David G
  • 94,763
  • 41
  • 167
  • 253