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

如何用有状态Lambda转换整数序列实现数字字面量运算符模板

原代码问题

原有实现中折叠表达式对weight的重复修改存在未定义行为隐患,虽依赖逗号运算符的左序求值暂时可用,但可读性差且会触发编译器警告,同时std::pow在constexpr上下文的可用性受编译器版本限制。

核心需求实现:有状态lambda映射整数序列

可以借助boost::mp11::mp_for_each遍历整数序列,配合可变捕获的有状态lambda完成权值的计算和映射,示例实现如下:

#include <string_view>
#include <cstdint>
#include <iostream>
#include <boost/mp11/integer_sequence.hpp>
#include <boost/mp11/algorithm.hpp>
using namespace boost::mp11;

template <char... Cs>
[[nodiscard]] constexpr auto operator""_c(){
    constexpr int len = sizeof...(Cs);
    // 生成0到len-1的整数序列
    using seq = make_index_sequence<len>;
    
    int val = 0;
    int weight = 1;
    // 反向遍历整数序列,从最低位开始计算权值,避免除法和pow调用
    mp_for_each<mp_reverse<seq>>([&](auto I){
        val += (Cs - '0') * weight;
        weight *= 10;
    });
    return val;
}

int main(){
    std::cout << 0_c  << std::endl;
    std::cout << 00_c << std::endl;
    std::cout << 01_c << std::endl;
    std::cout << 123_c << std::endl;
}

如果需要把<0,1,2>这类序列直接转换为<100,10,1>的编译期整数序列,可以用编译期计算的方式实现:

template<size_t N, size_t... Is>
constexpr auto make_weight_seq_impl(std::index_sequence<Is...>) {
    return index_sequence<((void)Is, size_t(std::pow(10, N - 1 - Is)))...>{};
}

template<size_t N>
constexpr auto make_weight_seq() {
    return make_weight_seq_impl<N>(std::make_index_sequence<N>{});
}

// 调用示例,生成<100,10,1>序列
using weight_seq_3 = decltype(make_weight_seq<3>());

优化建议

  • 完全避开std::pow调用,所有整数权值都可以用编译期乘法计算,保证constexpr上下文的兼容性
  • 反向遍历计算权值的方式不需要做除法,性能更高也不会出现整数截断问题
  • 如果需要完全编译期求值,可以把权值计算全部放到模板元编程逻辑中,运行时直接返回常量值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 12:18:02