Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turning #ifdef's into a template metaprogram in C++

I have the following code inside a C++ class:

class Features
{
    #define Feature_Size_A 12345
    #define Feature_Size_B 45678
    #define Feature_Size_C 78901
    //#define Feature_Size_D 14725

    const int Feature_Sum = 0
    #ifdef Feature_Size_A
        + Feature_Size_A
    #endif
    #ifdef Feature_Size_B
        + Feature_Size_B
    #endif
    #ifdef Feature_Size_C
        + Feature_Size_C
    #endif
    #ifdef Feature_Size_D
        + Feature_Size_D
    #endif
        ;

    #ifdef Feature_Size_A
        static float Feature_A[Feature_Size_A];
    #endif
    #ifdef Feature_Size_B
        static float Feature_B[Feature_Size_B];
    #endif
    #ifdef Feature_Size_C
        static float Feature_C[Feature_Size_C];
    #endif
    #ifdef Feature_Size_D
        static float Feature_D[Feature_Size_D];
    #endif
};

I used to comment out features, like line 4, to compile and run different tests. But now I'd like to have the class as a template, so I can instantiate several versions with different features turned on or off in the same program.

I'm thinking of something like this:

template <bool Feature_A, bool Feature_B, bool Feature_C, bool Feature_D>
class Features
{
    ...
};

Features<true, true, true, false> f;

I tried with boost::mpl:vector's but I'm struggling harshly.

BTW: This is not the complete code. The original code has 25 features.

I'm thankful for every idea not involving macros :-)

like image 754
Dominic Hofer Avatar asked Sep 05 '12 13:09

Dominic Hofer


People also ask

What is turning explain?

Turning is a machining process used to make cylindrical parts, where the cutting tool moves in a linear fashion while the workpiece rotates. Commonly performed with a lathe, turning reduces the diameter of a workpiece, typically to a specified dimension, and produces a smooth part finish.

What is the turning process?

Turning is the most common lathe machining operation. During the turning process, a cutting tool removes material from the outer diameter of a rotating workpiece. The main objective of turning is to reduce the workpiece diameter to the desired dimension. There are two types of turning operations, rough and finish.

What is the use of turning?

It is done for making internal holes of very accurate diameters. For example, a 6mm hole is made by drilling with 5.98 mm drill bit and then reamed to accurate dimensions. Both standard and non-standard screw threads can be turned on a lathe using an appropriate cutting tool.


2 Answers

Type lists can be used to solve this problem.

template<unsigned num, unsigned size, typename T>
class Feature : public T
{
public:
    static float feature[size];
    static const unsigned int feature_sum = size + T::feature_sum;
};
template<unsigned num, unsigned size, typename T>
float Feature<num, size, T>::feature[size];
class Tail { 
public:
    static const unsigned feature_sum = 0; 
};

template<unsigned num, unsigned size, typename T>
float* get_feature_arr(Feature<num, size, T>& ref) 
{
    return ref.feature;
}

int main() {
    Feature<1, 12345, Feature<2, 45678, Feature<4, 78901, Tail>>> TripleFeatures;
    auto first = get_feature_arr<1>(TripleFeatures);
    auto third = get_feature_arr<4>(TripleFeatures);
    auto size = TripleFeatures.feature_sum;
}

This can also be used to access any feature, regardless of what other features are or aren't in the list.

Edit: I nubbed up some of the details, like not defining the array and trying to have "3features" as an identifier. Le fixed. Code compiles GCC 4.7.1.

like image 86
Puppy Avatar answered Oct 28 '22 15:10

Puppy


Why not use statically allocated arrays?

#include <stdio.h>

template <bool Feature_A, bool Feature_B, bool Feature_C, bool Feature_D>
class Features
{
    static const int Feature_Size_A = 12345;
    static const int Feature_Size_B = 45678;
    static const int Feature_Size_C = 78901;
    static const int Feature_Size_D = 14725;
    static const int Feature_Sum = 0
        + Feature_A ? Feature_Size_A : 0
        + Feature_B ? Feature_Size_B : 0
        + Feature_C ? Feature_Size_C : 0
        + Feature_D ? Feature_Size_D : 0
    ;

public:
    static float Feature_Vector_A[Feature_A ? Feature_Size_A : 0];
    static float Feature_Vector_B[Feature_B ? Feature_Size_B : 0];
    static float Feature_Vector_C[Feature_C ? Feature_Size_C : 0];
    static float Feature_Vector_D[Feature_D ? Feature_Size_D : 0];
};

Features<true, true, true, true> f1;
Features<true, true, true, false> f2;

int main()
{
    printf("%d %d\n", sizeof(f1.Feature_Vector_D), sizeof(f2.Feature_Vector_D));
}

Output:

58900 0
like image 21
user1202136 Avatar answered Oct 28 '22 13:10

user1202136