Перечисляемый класс C ++ в качестве параметра шаблона переменной - PullRequest
1 голос
/ 26 февраля 2020

Я пытаюсь оптимизировать некоторые функции во время компиляции, используя класс enum в качестве параметра шаблона.

Скажем, например,

enum class Color { RED, BLACK };

Теперь я хотел бы определить метод

void myMethod<Color c> () {
 if( c == Color::RED ) { ... }
 if( c == Color::BLACK ) { ... }
}

И я бы хотел, чтобы компилятор сделал 2 копии myMethod и удалил мертвый код во время оптимизации (это для ядер CUDA, поэтому для меня важна скорость и использование регистров)

Однако, похоже, что когда я вызываю метод, используя

void doSomething( const Color c ) {
 myMethod<c>();
}

MSV C, жалуется на то, что «выражение должно иметь постоянное значение». Я ожидал, что компилятор будет достаточно умен, чтобы скомпилировать версию myMethod с каждой возможной версией перечисления. Разве это не так? Могу ли я заставить его без безобразного переключателя в doSomething?

Спасибо за помощь!

1 Ответ

4 голосов
/ 26 февраля 2020

Вы должны выбрать время выполнения v c время компиляции. Версия во время компиляции может выглядеть примерно так:

enum class Color { RED, BLACK };

template < Color c>  
void myMethod () {
    if constexpr ( c == Color::RED ) { std::cout << "RED" << std::endl; }
    if constexpr ( c == Color::BLACK ) { std::cout << "BLACK" << std::endl; }
}   

int main()
{   
    myMethod<Color::RED>( );
    myMethod<Color::BLACK>( );
}

Но если вы хотите во время выполнения переключиться на специализацию, генерируемую во время компиляции, вам нужно переключить все возможные значения:

enum class Color { RED, BLACK };

template < Color c>  
void myMethod () {
    if constexpr ( c == Color::RED ) { std::cout << "RED" << std::endl; }
    if constexpr ( c == Color::BLACK ) { std::cout << "BLACK" << std::endl; }
}

void RuntimeDispatch( Color c ) 
{
    if ( c == Color::RED ) { myMethod<Color::RED>(); }
    if ( c == Color::BLACK ) { myMethod<Color::BLACK>(); }
}   

int main()
{   
    RuntimeDispatch( Color::RED );
    RuntimeDispatch( Color::BLACK );
}

Нет просто никакого способа использовать переменную времени выполнения в качестве параметра шаблона, поскольку она просто не является постоянной времени компиляции.

если вам нужно использовать более старый компилятор, вы можете заменить constexpr if со специализацией шаблона:

template < Color c> void myMethod ();

template <> void myMethod< Color::RED >() { std::cout << "RED" << std::endl; }
template <> void myMethod< Color::BLACK >() { std::cout << "BLACK" << std::endl; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...