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

C++17下基于SFINAE为file_logger条件定义severity成员函数

为file_logger添加特定Severity的成员函数(带SFINAE编译时检查)

现有file_logger结构体实现

struct file_logger{
    logger &__logger;
    const int32_t __log_fd;
    friend class logger;
    template <severity sev, typename... Args>
    inline void log(Args... args);
    template <severity sev, char sep, typename... Args>
    inline void log_s(int32_t log_fd, Args... args);
private:
    file_logger(logger &l, const int32_t &fd) : __logger(l), __log_fd(fd) {}
};
template <severity sev, typename... Args>
inline void file_logger::log(Args... args){
    __logger.log<sev>(__log_fd, args...);
}
template <severity sev, char sep, typename... Args>
inline void file_logger::log_s(int32_t log_fd, Args... args){
    __logger.log_s<sev, sep>(__log_fd, args...);
}

需求说明

为避免每次编写log<severity::INFO>这类繁琐代码,需要给file_logger添加info、warn、error、debug等对应特定severity枚举值的快捷成员函数,示例如下:

/* 假设info已在file_logger中声明 */
template<typename... Args>
inline void file_logger::info(Args... args){
    __logger.log<severity::INFO>(__log_fd, args...);
}

同时需满足以下编译时检查要求:

  • 仅当调用对应severity枚举不存在的成员函数时,触发编译错误;
  • 未被调用的无效模板函数会被编译器自动忽略;
  • 基于C++17的SFINAE机制实现条件声明与定义。

解决方案

1. 定义编译期判断severity合法性的辅助工具

首先需要一个编译期常量函数,用来判断给定的severity枚举值是否有效。假设你的severity枚举定义如下(可根据实际情况调整):

#include <type_traits>

enum class severity {
    INFO,
    WARN,
    ERROR,
    DEBUG
};

// 编译期检查severity值是否合法
constexpr bool is_valid_severity(severity s) noexcept {
    switch(s) {
        case severity::INFO:
        case severity::WARN:
        case severity::ERROR:
        case severity::DEBUG:
            return true;
        default:
            return false;
    }
}

2. 修改file_logger,添加带SFINAE检查的快捷成员函数

将每个快捷函数(如info、warn)声明为模板函数,通过std::enable_if_t控制其可见性:只有当对应的severity值合法时,该函数模板才会被编译器纳入候选;否则会被SFINAE机制排除。

struct file_logger{
    logger &__logger;
    const int32_t __log_fd;
    friend class logger;
    template <severity sev, typename... Args>
    inline void log(Args... args);
    template <severity sev, char sep, typename... Args>
    inline void log_s(int32_t log_fd, Args... args);

    // INFO级别的快捷函数
    template<typename... Args, std::enable_if_t<is_valid_severity(severity::INFO), int> = 0>
    inline void info(Args... args){
        __logger.log<severity::INFO>(__log_fd, args...);
    }

    // WARN级别的快捷函数
    template<typename... Args, std::enable_if_t<is_valid_severity(severity::WARN), int> = 0>
    inline void warn(Args... args){
        __logger.log<severity::WARN>(__log_fd, args...);
    }

    // ERROR级别的快捷函数
    template<typename... Args, std::enable_if_t<is_valid_severity(severity::ERROR), int> = 0>
    inline void error(Args... args){
        __logger.log<severity::ERROR>(__log_fd, args...);
    }

    // DEBUG级别的快捷函数
    template<typename... Args, std::enable_if_t<is_valid_severity(severity::DEBUG), int> = 0>
    inline void debug(Args... args){
        __logger.log<severity::DEBUG>(__log_fd, args...);
    }

private:
    file_logger(logger &l, const int32_t &fd) : __logger(l), __log_fd(fd) {}
};

// 原模板函数的实现保持不变
template <severity sev, typename... Args>
inline void file_logger::log(Args... args){
    __logger.log<sev>(__log_fd, args...);
}
template <severity sev, char sep, typename... Args>
inline void file_logger::log_s(int32_t log_fd, Args... args){
    __logger.log_s<sev, sep>(__log_fd, args...);
}

3. 扩展支持log_s版本(可选)

如果需要为log_s也添加对应severity的快捷函数,同样可以用SFINAE实现:

// 在file_logger结构体中添加以下内容:
template<char sep = ' ', typename... Args, std::enable_if_t<is_valid_severity(severity::INFO), int> = 0>
inline void info_s(Args... args){
    __logger.log_s<severity::INFO, sep>(__log_fd, args...);
}

template<char sep = ' ', typename... Args, std::enable_if_t<is_valid_severity(severity::WARN), int> = 0>
inline void warn_s(Args... args){
    __logger.log_s<severity::WARN, sep>(__log_fd, args...);
}

// 同理添加error_s、debug_s...

实现原理

  • 利用C++17的std::enable_if_t结合编译期常量表达式is_valid_severity,实现SFINAE机制:当对应的severity值非法时,std::enable_if_t会导致模板参数推导失败,编译器自动忽略该函数模板;
  • 只有当调用某个快捷函数且对应的severity枚举值存在时,函数模板才会被实例化;如果severity枚举中没有对应的取值,调用该快捷函数会触发编译错误——因为所有候选函数模板都被SFINAE排除,无匹配的函数可用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:53:12