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

编译时移除string_view中子串的方法及DBG宏优化问询

解决嵌套DBG宏的编译时字符串清理问题

要实现你期望的嵌套DBG宏输出效果,核心是在编译时处理#expression生成的原始字符串,移除所有宏调用形式的DBG(前缀,同时保留表达式的结构。下面是完整的实现方案,基于C++17/20的constexpr特性:

完整代码实现

#include <iostream>
#include <string_view>

// 编译时计算清理后的字符串长度
constexpr size_t calculate_cleaned_length(std::string_view s) {
    constexpr std::string_view target = "DBG(";
    size_t len = s.size();
    size_t pos = 0;
    while ((pos = s.find(target, pos)) != std::string_view::npos) {
        // 替换"DBG("为"(", 每替换一次减少3个字符(4-1=3)
        len -= target.size() - 1;
        pos += target.size();
    }
    return len;
}

// 编译时将原始字符串填充到目标数组,替换所有"DBG("为"("
template<size_t N>
constexpr void fill_cleaned_string(char (&dest)[N], std::string_view s) {
    constexpr std::string_view target = "DBG(";
    size_t dest_idx = 0;
    size_t pos = 0;
    while (pos < s.size()) {
        // 检查当前位置是否匹配"DBG("
        if (pos + target.size() <= s.size() && s.substr(pos, target.size()) == target) {
            dest[dest_idx++] = '(';
            pos += target.size();
        } else {
            dest[dest_idx++] = s[pos++];
        }
    }
    dest[dest_idx] = '\0'; // 确保字符串以终止符结尾
}

// 调试日志函数,与你原版本一致
template<typename T>
inline constexpr T debug_log(const std::string_view& raw_expression, T&& x) {
    std::cout << raw_expression << " = " << x << '\n';
    return std::forward<T>(x);
}

// 改进后的DBG宏,内置编译时字符串清理逻辑
#define DBG(expression) \
    []() constexpr { \
        constexpr std::string_view raw_expr = #expression; \
        constexpr size_t cleaned_size = calculate_cleaned_length(raw_expr); \
        constexpr char cleaned_buf[cleaned_size + 1]{}; \
        fill_cleaned_string(cleaned_buf, raw_expr); \
        return debug_log(std::string_view(cleaned_buf), expression); \
    }()

// 测试代码
int main() {
    DBG(DBG(5*3)+DBG(20/4));
    // 输出结果:
    // 5*3 = 15
    // 20/4 = 5
    // (5*3)+(20/4) = 20
    return 0;
}

关键实现细节

  1. 编译时字符串长度计算:
    calculate_cleaned_length会遍历原始字符串,统计所有DBG(出现的次数,计算出清理后的字符串总长度。这一步完全在编译时完成,不会带来运行时开销。

  2. 编译时字符串替换:
    fill_cleaned_string将原始字符串中的每一处DBG(替换为(,并填充到一个编译时分配的字符数组中。使用模板数组参数确保大小匹配,避免越界。

  3. 改进的DBG宏:
    利用constexpr lambda在编译时完成字符串清理工作:

    • 首先通过#expression获取原始表达式字符串;
    • 计算清理后的长度并创建对应大小的constexpr字符数组;
    • 填充清理后的字符串;
    • 调用debug_log传入清理后的字符串和求值后的表达式结果。
  4. 嵌套调用的执行顺序:
    内层的DBG调用会先执行,输出各自的表达式和结果;外层DBG会在所有内层调用完成后,输出清理后的合并表达式和最终结果,完全符合你的期望。

兼容性说明

  • 代码基于C++17标准,需要编译器支持constexpr lambda和constexpr std::string_view操作(GCC 7+、Clang 5+、MSVC 2017+都支持)。
  • 如果使用C++20,可以将fill_cleaned_string中的子串检查替换为starts_with,代码会更简洁:
    if (s.substr(pos).starts_with(target)) {
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:10:33