开发者

Remove/Insert code at compile time without duplication in C++

开发者 https://www.devze.com 2023-04-10 16:51 出处:网络
I have a template class that is taking in a couple of types. One type is there just to determine policies. That class determines how a function may work in certain cases.

I have a template class that is taking in a couple of types. One type is there just to determine policies. That class determines how a function may work in certain cases.

Let's say this is one of the function:

/* this code is part of a class */

    template <typename T, typename T_Policy> // Not important but just showing the template parameters of the class

    void Allocate(unsigned int numElements)
    {
      // Some code here
      while (someCondition) // Other functions don't have the loop, this is just an example
      {
        // Some code here

        if (T_Policy::trackElements) { /* some code here */ }
        if (T_Policy::verbose) { /* some code here */ }
        if (T_Policy::customManager) { /* some code here */ }
        /* and a few other policies */
      }
      // Some more code here
    }

I would like the lines of code that are using the policies to be compiled out instead of relying on if statements. One obvious way is to put the while loop in overloaded functions each taking a dummy object with a specific policy type. But that means a lot of code duplication.开发者_如何学JAVA Similar approaches with template specialization will result in code duplication as well.

Is there a way to compile out the code without code duplication?


If the values in the policy are const, the compiler can optimize the generate code because it can see which if is always true or always false.


You can always change code

   if (T_Policy::trackElements) { /* some code here */ }

into

template <bool b>
void trackElementPhase() {
  /* some code here */
}

template <>
void trackElementPhase<false>() {} // empty body

 ... later in the code

     trackElementPhase<T_Policy::track_elements>();

Of course T_Policy::track_elements has to be compile time constant for this.

However, I wouldn't bother. The compiler is likely clever enough to optimize out code in

   if (T_Policy::trackElements) { /* some code here */ }

if the condition is compile time constant.


You can use recursive templates to make a list of policies, which all get applied, e.g.:

#include <iostream>
template <typename Policy, typename Next=void>
struct policy_list {
  static void apply() {
    Policy::implement();
    Next::apply();
  }
};

template <typename Policy>
struct policy_list<Policy, void> {
  static void apply() {
    Policy::implement();
  }
};

struct first_policy {
  static void implement() { std::cout << "Policy 1" << std::endl;  }
};

struct second_policy {
  static void implement() { std::cout << "Policy 2" << std::endl; }
};

int main() {
  typedef policy_list<first_policy, policy_list<second_policy> > policy;
  while (1) {
    policy::apply();
  }
}

For three policies you would need to change the typedef to:

typedef policy_list<first_policy, policy_list<second_policy, policy_list<third_policy> > > policy;

Then all you need to do is produce the right policy list at compile time. This could be done by an external part of your build system that generates a header file with a typedef, or it could be done with either preprocessor or template magic, depending on what exactly dictates what your policies are.

If you have C++11 available you can simplify the policy_list somewhat using variadic templates.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号