Since you said in a comment that your index is always a template parameter, then you can indeed make the branching at compile-time instead of runtime. Here is a possible solution using std::enable_if
:
#include <iostream>
#include <type_traits>
struct f32x4
{
float fLow[2];
float fHigh[2];
f32x4(float a, float b, float c, float d)
{
fLow[0] = a;
fLow[1] = b;
fHigh[0] = c;
fHigh[1] = d;
}
template <int x>
float& get(typename std::enable_if<(x >= 0 && x < 2)>::type* = 0)
{
return fLow[x];
}
template <int x>
float& get(typename std::enable_if<(x >= 2 && x < 4)>::type* = 0)
{
return fHigh[x-2];
}
};
int main()
{
f32x4 f(0.f, 1.f, 2.f, 3.f);
std::cout << f.get<0>() << " " << f.get<1>() << " "
<< f.get<2>() << " " << f.get<3>(); // prints 0 1 2 3
}
Regarding performance, I don't think there will be any difference since the optimizer should be able to easily propagate the constants and remove dead code subsequently, thereby removing the branch altogether. However, with this approach, you get the benefit that any attempts to invoke the function with an invalid index will result in a compiler error.