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

C++17下如何让MSVC的__popcnt64支持在constexpr函数中使用

C++17 MSVC环境constexpr 64位位计数适配方案

MSVC提供的__popcnt64内置函数在C++17标准下不支持constexpr调用,无法直接替换GCC的__builtin_popcountll实现编译期位计数需求,可通过以下两种方案解决:

方案1:纯标准C++17实现(推荐)

手写无编译器依赖的constexpr位计数逻辑,开启O2优化后MSVC会自动将该逻辑编译为原生popcnt指令,运行性能和内置函数完全一致。

首先实现通用constexpr位计数函数:

#include <cstdint>

constexpr int popcountll(uint64_t mask) noexcept {
    mask = mask - ((mask >> 1) & 0x5555555555555555);
    mask = (mask & 0x3333333333333333) + ((mask >> 2) & 0x3333333333333333);
    mask = (mask + (mask >> 4)) & 0x0F0F0F0F0F0F0F0F;
    return static_cast<int>((mask * 0x0101010101010101) >> 56);
}

修改你的成员函数即可正常使用:

[[nodiscard]] constexpr int count() const noexcept {
    // 如果mask是有符号int64_t,需改为return popcountll(static_cast<uint64_t>(mask));
    return popcountll(mask);
}

方案2:跨编译器兼容实现

如果需要同时兼容GCC和MSVC环境,可通过预编译宏区分编译器,GCC继续用原生内置函数,MSVC用自定义实现:

#include <cstdint>

#ifdef __GNUC__
constexpr int popcountll(uint64_t mask) noexcept {
    return __builtin_popcountll(mask);
}
#else
constexpr int popcountll(uint64_t mask) noexcept {
    mask = mask - ((mask >> 1) & 0x5555555555555555);
    mask = (mask & 0x3333333333333333) + ((mask >> 2) & 0x3333333333333333);
    mask = (mask + (mask >> 4)) & 0x0F0F0F0F0F0F0F0F;
    return static_cast<int>((mask * 0x0101010101010101) >> 56);
}
#endif

成员函数调用方式和方案1完全一致。

注意事项

  • 请确保传入位计数函数的参数为无符号64位类型uint64_t,若原成员变量mask为有符号int64_t,调用前需要做无符号转换,避免右移操作出现符号位扩展导致计算错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 07:36:03