templates, type traits and C++17 if constexpr
Posted: December 19th, 2017, 10:06 am
It sure is nice to have all these great features allowing a programmer to be so lazy. So, normally, I put stuff like DotProduct, Normalize, Length and LengthSq in the vector classes that they need to work on, but lately, I've been messing around with templates and some C++17 features as Visual Studio allows. One of them is if constexpr. What this does is allows you to, in a function, determine which code path to COMPILE not just run as long as the condition is a constexpr value.
Here is my DotProduct example
Now I can write two function instead of 6. Granted, this could be done without the if constexpr, but you would pay a runtime branching penalty. This way, it's decided at compile time which branch to take.
Here is my DotProduct example
Code: Select all
// Only dealing with float base types; _Vec2<float>, _Vec3<float>
// Just to make code look nicer in function
template<class VecType>
constexpr void VecType_Error()
{
static_assert( !(is_vec2 && is_vec3), "Requires VecType to be a _Vec2<float or _Vec3<float>." );
}
template<class VecType>
float operator*( const VecType& lhs, const VecType& rhs )
{
return DotProduct( lhs, rhs );
}
template<class VecType>
float DotProduct( const VecType& lhs, const VecType& rhs )
{
// absurd value indicating you passed in something you shouldn't have
float result = std::limits<float>::max();
constexpr auto is_vec2 = std::is_same_v<VecType, Vec2>;
constexpr auto is_vec3 = std::is_same_v<VecType, Vec3>;
// Test for Vec2
if constexpr( is_vec2 )
{
result = lhs.x * rhs.x + lhs.y * rhs.y;
}
else if constexpr( is_vec3 )
{
result = lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
}
else
{
// Will show error message in Output window if path is compiled
VecType_Error<VecType>();
}
return result;
}