Использование CRTP для детерминированной генерации кода

Недавно я начал изучать шаблоны и, в частности, 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

Это прекрасно работает, делает именно то, что я хочу. Проблема, с моей точки зрения, в том, что утверждения должны быть ненужными. Поскольку я имею дело с константными выражениями, компилятор должен иметь все необходимое, чтобы просто пропустить переход и знать, как выполнить первую часть для класса B и обе части для класса C.

Я хотел бы заработать на этом и, в частности, сказать компилятору удалить разделы, которые не нужны для конкретного класса, чтобы избежать ненужных ветвлений во время выполнения. К сожалению, я понятия не имею, как это сделать, есть идеи? заранее спасибо

редактировать

В ответ на некоторые удивительные предложения constexpr в C ++ 17 if expression является почти идеальным решением, о котором я даже не подозревал, но, к сожалению, не могу его использовать. Я ограничен использованием C ++ 14.

0

Решение

Эмуляция 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 так же.

0

Другие решения

Если вы заботитесь о производительности, компилятор, скорее всего, оптимизирует все «мертвые» ветки и даже if условие, если он может оценить его во время компиляции.

Что еще хуже, все ветви должны быть хорошо сформированы до C ++ 17 constexpr if, В этом случае вы можете «передать» функциональность специальным функциям (статическим членам) и использовать специализацию для вызова правильной функции. Посмотрите ответ @R Sahu для примера.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector