1

Lets say I have the following class:

struct Color
{
   enum {
      blue,
      red,
      unknown
   };
};

I would like to test in compile time if the class Color has the unknown value.

I thought the following could work but it is currently returning an incorrect result.

#include <iostream>

template <typename T, typename U = T>
struct test
{
  static constexpr bool value = false;
};

template <typename T>
struct test<T, decltype(T::unknown)>
{
  static constexpr bool value = true;
};

int main()
{
  std::cout << test<Color>::value << std::endl; //prints 0
}

Could you provide some insight on how I can accomplish the check? Or what is wrong with my example?

Thanks

Jonathan
  • 552
  • 1
  • 4
  • 10

1 Answers1

2

When you write test<Color>, we first instantiate the primary specialization of test, which includes filling in the default template parameters. So we get test<Color, Color>.

Next, we try to see if any of the specializations match. The one specialization is for test<Color, Color::<unnamed>>. This doesn't match, so we stick with the primary!

This type mismatch is why void_t exists - so that our defaulted template parameter on the primary can match the specialization:

template <typename T, typename U = void>
//                              ~~~~~~~
struct test
{
  static constexpr bool value = false;
};

template <typename T>
struct test<T, void_t<decltype(T::unknown)>>
//             ~~~~~~~                    ~
{
  static constexpr bool value = true;
};

Also, prefer to just inherit from false_type and true_type, respectively.

Barry
  • 286,269
  • 29
  • 621
  • 977