C++ 枚举类作为可变模板参数

Nor*_*let 1 c++ enums templates

我试图通过使用枚举类作为模板参数在编译时优化一些函数。

比如说

enum class Color { RED, BLACK };
Run Code Online (Sandbox Code Playgroud)

现在,我想定义一个方法

void myMethod<Color c> () {
 if( c == Color::RED ) { ... }
 if( c == Color::BLACK ) { ... }
}
Run Code Online (Sandbox Code Playgroud)

我希望编译器myMethod在优化过程中制作 2 个副本并消除死代码(它适用于 CUDA 内核,因此速度和寄存器使用对我来说很重要)

但是,似乎当我使用

void doSomething( const Color c ) {
 myMethod<c>();
}
Run Code Online (Sandbox Code Playgroud)

MSVC 抱怨“表达式必须有一个常量值”。我期望编译器足够聪明,可以myMethod用枚举的每个可能版本编译一个版本。不是这样吗?我可以强迫它,没有一个丑陋的开关doSomething吗?

谢谢你的帮助 !

Kla*_*aus 5

您必须决定运行时 vc 编译时。编译时版本可以是这样的:

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>( );
}
Run Code Online (Sandbox Code Playgroud)

但是如果你想在运行时切换到编译时生成的专业化,你必须切换所有可能的值:

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 );
}
Run Code Online (Sandbox Code Playgroud)

根本没有办法使用运行时变量作为模板参数,因为它根本就不是编译时常量。

如果您必须使用较旧的编译器,您可以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; }
Run Code Online (Sandbox Code Playgroud)