You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++:除decltype(枚举成员)外,获取枚举类型的其他可行方法

问题:获取枚举类型的替代方法(除了decltype(enum_name::any_value))

我定义了如下枚举:

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

为了能通过编写新接口实现即可替换代码中的任意网络库,同时出于性能需求(因此选择C++而非Python,即便用Python最快的库仍不够快),我计划采用CRTP模式编写接口。

此外,为减少运行时分支,我希望为URL使用模板,为每个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) {
    ...
}
...

请问除了使用decltype(enum_name::any_value)之外,还有其他获取枚举类型的方法吗?


回答

当然有几种更直接、可读性更强的方式来获取枚举类型,无需依赖枚举的具体值:

1. 直接使用枚举类型名

这是C模板中处理枚举参数的标准写法,C11及以后完全支持。直接将枚举类型作为模板参数的类型约束,代码更直观且类型安全性更高:

// 直接用HTTPRequestMethods作为模板参数类型
template <HTTPRequestMethods 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 <HTTPRequestMethods HTTPRequestMethod>
    std::string_view getBody(URL<HTTPRequestMethod> url) {
        return static_cast<InterfaceImplementation*>(this)->getBody<HTTPRequestMethod>(url);
    }
};

// APIWrapper中的模板声明也同步调整
struct APIWrapper : InternetInterface<APIWrapper> {
    ...
    template <HTTPRequestMethods HTTPRequestMethod>
    std::string_view getBody(URL<HTTPRequestMethod> url_);
    ...
};

// 特化写法保持不变,依然清晰
template <>
std::string_view APIWrapper::getBody(URL<HTTPRequestMethods::GET> url) {
    ...
}

这种方式的优势在于:编译器会自动校验模板实参是否属于HTTPRequestMethods枚举的合法值,避免传入非法整数的风险,而decltype(HTTPRequestMethods::GET)本质是枚举的底层整数类型(默认是int),无法提供这种类型校验。

2. 自定义枚举类型别名(语法糖)

如果枚举名称过长,可以先定义一个短别名再使用,本质和第一种方法一致,但能简化代码:

using HttpMethod = HTTPRequestMethods;

template <HttpMethod Method>
struct URL {
    // 实现同前
};

3. 获取枚举底层类型(仅特定场景适用)

如果需要的是枚举对应的底层整数类型(而非枚举类型本身),可以用std::underlying_type_t<HTTPRequestMethods>,但这通常用于枚举与整数的转换场景,并不匹配你当前需要约束模板参数为合法枚举值的需求。


内容的提问来源于stack exchange,提问作者arniiiii_ua

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 23:40:30