How to make _t version of SFINAE struct exposing static member value?

Viewed 104

I have that code that recognizes which GL type you need to use based on C++ types. I want to make a _t version of it (like std::decay_t or std::enable_if_t) but expose int constant value

template <typename T, typename = void> struct GLType {};

template <typename T>
struct GLType<T, std::enable_if_t<std::is_same_v<std::remove_pointer_t<std::decay_t<T>>, float>>> {
   const static constexpr int type = GL_FLOAT;
};

template <typename T>
struct GLType<T, std::enable_if_t<std::is_same_v<std::remove_pointer_t<std::decay_t<T>>, double>>> {
   const static constexpr int type = GL_DOUBLE;
};

My first try was

template <typename T>
using GLType_t = GLType<T>::type;

but that doesn't work. Is it even possible to return value instead of type in the same way?
In the end, I want something like

int a = GLType_t<float>;
// instead of
int a = GLType<float>::type; // which works fine btw
2 Answers

You appear to be looking for variable-templates which allow you to do this:

template <typename T>
inline constexpr int GLType_t = GLType<T>::type;

and then you can use it like this:

int a = GLType_t<float>;

Also, I strongly suggest that you name the int member something like value instead of type. Names matter, and type is just the wrong name for a member that is not actually a type.

The @cigien's answer provided the way to go with variable template.

However, I would like to propose a less typing approach using s if constexpr. The entire boiler-plate traits code will meltdown to simply, a template-function:

#include <type_traits>

template <typename T>
constexpr auto GLTypeHelper() noexcept
{
   // assert is the T is not either float or double
   static_assert(std::is_same_v<T, float> || std::is_same_v<T, double>, " T should be float or double");
   
   if constexpr (std::is_same_v<T, float>) 
      return GL_FLOAT;
   else if constexpr (std::is_same_v<T, double>) 
      return GL_DOUBLE;
};

// variable template for GLType_v
template <typename T>
inline constexpr int GLType_v = GLTypeHelper<T>(); // calls the `GLTypeHelper()`

You will use it like

constexpr int a = GLType_v<float>;
constexpr int b = GLType_v<double>;

and ofcourse, since GL_FLOAT and GL_DOUBLE are values, not a types, change the ::type -> ::value, and _t -> _v!

Related