使用CRTP确定性地生成代码

时间:2018-02-05 19:51:31

标签: c++ templates constexpr crtp deterministic

我最近进入了模板魔法,特别是CRTP。我知道模板用于让编译器为我们生成代码,所以我想知道是否可以制作模板"决定"我们希望它包含在特定类中的函数的哪些部分。例如,如果我有以下代码:

crtp.h

#include <iostream>
using std::endl;
using std::cout;

template<class T>
class A {
public:
    void func() {
        constexpr unsigned short mask = T::GetMask();
        if (mask & 1) {
            /*
            Do Something
            */
            cout << "Mask 1" << endl;
        }
        if (mask & 1 << 3) {
            /*
            Do Something else
            */
            cout << "Mask 2" << endl;
        }
    }
};

class B : public A<B> {
    friend class A<B>;
protected:
    static constexpr unsigned short GetMask() { return 0x0001; }
};

class C : public A<C> {
    friend class A<C>;
protected:
    static constexpr unsigned short GetMask() { return 0x0009; }
};

的main.cpp

#include "ctrp.h"
#include <iostream>
#include <vector>

using std::cout;
using std::vector;
using std::getchar;
using std::endl;

int main() {
    B b;
    C c;
    cout << "B:" << endl;
    b.func();
    cout << endl << "C:" << endl;
    c.func();
    getchar();
}

执行时产生:

B:
Mask 1

C:
Mask 1
Mask 2

这很有效,完全符合我的要求。从我的观点来看,问题是if语句应该是不必要的。当我处理常量表达式时,编译器应该具有简单地跳过分支所需的一切,并且知道为B类执行第一部分以及为C类执行这两部分。

我想了解这一点,并特别告诉编译器删除特定类不必要的部分,以避免在运行时进行不必要的分支。不幸的是我不知道如何做到这一点,任何想法?提前致谢

修改

回应一些令人敬畏的建议C ++ 17的constexpr如果表达是一个近乎完美的解决方案,我不知道存在,但遗憾的是无法使用。我只能使用C ++ 14。

2 个答案:

答案 0 :(得分:1)

如果您关心性能,编译器很可能会优化所有“死”分支甚至if条件,如果它可以在编译期间对其进行评估。

更糟糕的是,所有分支都需要很好地形成,直到C ++ 17 constexpr if。在这种情况下,您可以将功能“外包”到特殊(静态成员)函数,并使用特化来调用正确的函数。请参阅@R Sahu的答案。

答案 1 :(得分:0)

使用模板元编程在编译时模拟if / else不起作用。你必须想象if / else是否使用不同的心态。

而不是

    if (mask & 1) {
        /*
        Do Something
        */
        cout << "Mask 1" << endl;
    }
    if (mask & 1 << 3) {
        /*
        Do Something else
        */
        cout << "Mask 2" << endl;
    }

你将不得不使用以下内容:

   function1_selector<mask & 1>::dostuff();
   function2_selector<mask & 1 << 3 >::dostuff();

,其中

template <bool> struct function1_selector
{
  static void dostuff() { /* Do nothing */ }
};

template <> struct function1_selector<true> // Specialize for true
{
   static void dostuff() { /* Do something useful */ }
};

同样为function2_selector添加代码。