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";
// (...)
}