Home > Back-end >  C how to get type of enum
C how to get type of enum

Time:01-23

I have such enum:

enum HTTPRequestMethods {GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH};

I would like to write interface for my code that then I'll be able to use any other internet library in my code just writing a new interface implementation. Because I need some speed (that's why I write my project in C , because in Python I tried it is slow even if use fastest libraries) I thought write the interface using CRTP.

Also I would like to use templates for URL for less branching in runtime, just writing specific function for every HTTPRequestMethod:

template <decltype(HTTPRequestMethods::GET) Method>
struct URL {
    explicit URL(std::string web_url, std::string path) : web_url(web_url), path(path) {}
    std::string web_url;
    std::string path;
};

template <typename InterfaceImplementation>
struct InternetInterface {

    template <decltype(HTTPRequestMethods::GET) HTTPRequestMethod>
    std::string_view getBody(URL<HTTPRequestMethod> url) {
        return static_cast<InterfaceImplementation>(this).getBody<HTTPRequestMethod>(url);
    }
};

struct APIWrapper : InternetInterface<APIWrapper> {
    
    ...

    template <decltype(HTTPRequestMethods::GET) HTTPRequestMethod>
    std::string_view getBody(URL<HTTPRequestMethod> url_);


private:
    ...
};

// template specializations:
// for GET
template <>
std::string_view APIWrapper::getBody(URL<HTTPRequestMethods::GET> url) {
    ...
}
...

Is there another way to get type of enum than decltype(enum_name::any_value) ?

CodePudding user response:

to answer your question - using decltype is a correct way to obtain a type of an enum.

TLDR

Keep in mind, that decltype yields you a type, in your case, the type of HTTPRequestMethods::GET and HTTPRequestMethods::POST is exactly the same - it will be HTTPRequestMethods.

You can verify it with static_assert and std::is_same_v like this:

static_assert(std::is_same_v<decltype(HTTPRequestMethods::GET), HTTPRequestMethods>,
                  "This should be the same");
static_assert(std::is_same_v<decltype(HTTPRequestMethods::PATCH), HTTPRequestMethods>,
                  "This should be the same");

What you need is a non-type template parameter as opposed to a type template parameter. Here is a small example:

template <HTTPRequestMethods Method>
struct URL {
    std::string web_url;
    std::string path;
};

template <>
struct URL<HTTPRequestMethods::PUT> {
    std::string put_only;
};

This way, the URL<HTTPRequestMethods::GET> and the URL<HTTPRequestMethods::PUT> are different types. Since these are different types, you can provide standard overloads:

void print_url(const URL<HTTPRequestMethods::GET>& url) {
    std::cout << "web_url = " << url.web_url << "\n";
    // (...)
}

void print_url(const URL<HTTPRequestMethods::PUT>& url) {
    std::cout << "put_only = " << url.put_only << "\n";
    // (...)
}
  • Related