c++c++20type-traits

Type trait providing the static member of a struct/class if available


I want to have a type trait for T that returns the value of a static member 'X' if it exists in T, otherwise a default value.

It can be done this way

// we define our type trait here 
template<typename T>  struct get_X  {  static constexpr int value = -1;  };

// and a specialization for types holding the required member
template<typename T>  static constexpr bool has_X = requires { T::X; };
template<typename T>  requires(has_X<T>) struct get_X<T>  {  static constexpr int value = T::X;  };

struct foo  {  static constexpr int X = 3;  };
struct bar  {  static constexpr int Y = 5;  };

static_assert (get_X<foo>::value ==  3);
static_assert (get_X<bar>::value == -1);

int main()  {}

This code works but is pretty cumbersome.

Moreover, if I want to have different type traits for other members like 'get_Y', it could lead to a lot of code.

Question: is there a simpler way to define such a type trait ?


Solution

  • Using if constexpr, you don't need partial specialisations:

    template<typename T>
    inline constexpr decltype(auto) get_X_v = []() -> decltype(auto) {
      if constexpr (requires { T::x; }) {
        return T::x;
      } else {
        return -1;
      }
    }();
    

    You might be able to inline this into wherever you use it and get rid of the trait entirely.