问题
I'm trying to optimize out some function at compile time by using an enum class as a template parameter.
Say for example
enum class Color { RED, BLACK };
Now, I would like to define a method
void myMethod<Color c> () {
if( c == Color::RED ) { ... }
if( c == Color::BLACK ) { ... }
}
And I would like the compiler to make 2 copies of myMethod
and eliminate the dead code during the optimisation (it's for CUDA kernels so speed and register usage is important to me)
However, seems like when I call the method using
void doSomething( const Color c ) {
myMethod<c>();
}
MSVC complains with "expression must have a constant value".
I was expecting the compiler to be clever enough to compile a version of myMethod
with each possible version of the enum. Is that not the case ? Can I force it to, without an ugly switch in doSomething
?
Thanks for your help !
回答1:
You have to decide for run-time vc compile-time. The compile time version can be something like that:
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>( );
}
But if you want in run-time switch to a compile-time generated specialization, you have to switch over all possible values:
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 );
}
There is simply no way to use a run time variable as a template parameter as it simply is never compile time constant.
if you have to use an older compiler, you can substitute the constexpr if
with template specialization:
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; }
来源:https://stackoverflow.com/questions/60409984/c-enum-class-as-a-variable-template-parameter