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

两款C++编译器对count_args函数是否为constexpr存在分歧

constexpr参数计数函数的编译器合法性问题

先看这段用于统计传入参数数量的代码:

#include <iostream>

constexpr static int count_args() {
    return 0;
}

template<typename... SS>
constexpr static int count_args(int &v, SS & ... restargs)
{
    constexpr int rest = count_args(restargs...);
    return rest + 1;
}

int main(int argc, char **argv) {
    int a,b;
    constexpr int count = count_args(a,b);
    std::cerr << "count: " << count << std::endl; // 预期输出'count: 2'
}

两款GCC版本的编译结果不同:

  • G++ 9.4.0可以正常编译运行,输出预期的count: 2
  • G++ 10.3.0编译时报错:
> g++ -std=c++17 -o cx2.exe cx2.cpp
cx2.cpp: In instantiation of 'constexpr int count_args(int&, SS& ...) [with SS = {int}]':
cx2.cpp:15:16: error: 'restargs#0' is not a constant expression
   15 |  constexpr int rest = count_args(restargs...);

结论

G++ 10.3.0的处理是正确的,这段代码不是合法的constexpr代码。

原因解释

C++标准规定,constexpr变量的初始化表达式必须是常量表达式。问题出在constexpr int rest = count_args(restargs...);这一行:

  • restargs是函数参数的引用,指向的是main函数里的自动变量a、b,这些变量的地址在编译期无法确定,不属于常量表达式范畴。
  • 调用count_args(a,b)时会逐层实例化模板函数,到第二层调用count_args(b)时,用这个指向自动变量的引用去初始化constexpr变量rest,违反了常量表达式的要求。

G++ 9.4.0属于旧版本编译器,对constexpr的检查不够严格,没捕捉到标准违规;而G10.3.0严格遵循C17标准规则,所以报错是符合规范的。

修正方案

去掉函数内部的constexpr变量定义,直接返回递归调用结果加1即可,编译期可直接推导参数数量,无需依赖常量表达式的引用:

#include <iostream>

constexpr static int count_args() {
    return 0;
}

template<typename... SS>
constexpr static int count_args(int &v, SS & ... restargs)
{
    return count_args(restargs...) + 1;
}

int main(int argc, char **argv) {
    int a,b;
    constexpr int count = count_args(a,b);
    std::cerr << "count: " << count << std::endl;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 20:05:22