Check if a type is defined via static_assert?

548 Views Asked by At

I have a situation where I have an enum that defines a list of jobs.

enum class job_t
{
  a,
  b,
  c,
};

Elsewhere I have classes that subclass an interface like

class job_interface
{
  public:
    virtual job_t get_job_type(void) const = 0;
    /* ... other methods snipped for simplicity */
}

What I want to do is verify for each value of the job_t enum that a class exists that subclasses job_interface with the same name. I have access to magic_enum so I am wondering if it's possible to translate the enum values to compile time strings and then detect if they're valid typenames via static_assert. It would also be nice if I could verify those classes were decendants of job_interface

Any suggestions on how I might achieve this?

1

There are 1 best solutions below

0
Passer By On BEST ANSWER

Identifier names can't be obtained from strings, even if they're compile time. The best you can do is macros, e.g. with X macros

#define JOB_IDS \
    X(a) \
    X(b) \
    X(c)

To define the enum

#define X(id) id,
enum class job_t {
    JOB_IDS
};
#undef X

Checking for existence is a bit hard. Checking for completeness is easier, which should suffice for your case. To check for completeness of a type T, we SFINAE on sizeof(T)

template<typename T>
constexpr auto is_complete(T*) -> decltype(!sizeof(T))
{
    return true;
}

constexpr auto is_complete(void*)
{
    return false;
}

Then bundle the completeness check together with the base class check

template<typename T>
constexpr auto check(T*) -> decltype(!sizeof(T))
{
    return std::is_base_of_v<job_interface, T>;
}

constexpr auto check(void*)
{
    return false;
}

Finally, we abuse the fact that struct a* is valid regardless of whether a is defined or not

#define X(id) \
static_assert(check((struct id*)nullptr), #id" has to be defined and inherit from job_interface");
JOB_IDS
#undef X

Live.