compile time template bernstein polynomial
You could check against the most common cases you expect to occur:

float a;
switch (k)
{
case 0:
    a = 1.0f;
    break;
case 1:
    a = val;
    break;
case 2:
    a = val*val;
    break;
// maybe some more common cases...
default:
    a = std::powf(val, k);
}


But I personally wouldn't do such optimizations unless you really see that there is some significant slowdown in your particular case and benchmarks show that such an optimization really does make a difference.