c++c++20static-assertcompile-time-constant

Check if a type is defined via static_assert?


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?


Solution

  • 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.