Meta programming

One of the first meta programming tricks I read about was a structure that calculated how many bits a integer type contained. I needed this calculation for an assignment at a university, where we needed a memory optimized bit vector. The teacher was warning us that he would use different architectures, where the number of bits in various integers types was’t always the same.

We found something like this and a new world of wonders opened up. The magic world of template meta programming.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

namespace meta_programming {
#ifdef _WIN32
    template<typename type> struct bitcount {

        template<type i> struct _bitcount {
            static constexpr size_t count = _bitcount<(i << 1)>::count + 1;
        };

        template<> struct _bitcount<0> {
            static constexpr size_t count = 0 ;
        };

        static constexpr size_t  count = _bitcount<type(1)>::count;
    };
#else
    template<typename type> struct bitcount {

        template<type i, int DU> struct _bitcount {
            static constexpr size_t count = _bitcount<(i << 1), DU>::count + 1;
        };

        template<int DU> struct _bitcount<0, DU> {
            static constexpr size_t count = 0;
        };

        static constexpr size_t count = _bitcount<type(1), 1>::count;
    };
#endif
}

int main(int argc, char* argv[]) {

    std::cout << meta_programming::bitcount<int>::count << std::endl;
    std::cout << meta_programming::bitcount<unsigned>::count << std::endl;
    std::cout << meta_programming::bitcount<long long>::count << std::endl;
    std::cout << meta_programming::bitcount<short>::count << std::endl;
    std::cout << meta_programming::bitcount<char>::count << std::endl;
    return 0;
}

>>> console
bit size of int: 32
bit size of unsigned: 32
bit size of long long: 64
bit size of short: 16
bit size of char: 8

Notes

GCC compiler tested on Coliru.

  • The code don’t compile on all compilers
    • VS 2017 compiles (had to add the #ifdef guard)
    • GCC 4.7 and 5.2 compiles with warnings
    • GCC 7.1 fails with “left operand of shift expression ‘[exp]’ is negative  [-fpermissive]
      • It compiles when only using the unsigned case
    • clang 3.8 fails “error: non-type template argument is not a constant expression  static constexpr size_t count = _bitcount<(i << 1), DU>::count + 1;
  • The “static constexpr size_t count = …;” could be replaced  “enum {count = …};
  • Need support for C++11 (“constexpr” and “long long”)

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *