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

C++传入函数返回的constexpr值时static_assert编译失败问题

问题原因

  • constexpr 函数只有传入的参数全部属于常量表达式时,才能在编译期求值得到常量结果,否则会退化为普通的运行期函数。
  • 函数模板 make_string 的形参 s 是数组引用,即使你传入的实参是字符串字面值 "abc",在 make_string 的函数体内部,s 的地址属于编译期无法确定的量(字符串字面值的最终地址要到链接期才能确定),因此访问 s[i] 的操作无法在编译期执行,has_char_a(s) 无法得到编译期常量,自然不满足 static_assert 要求操作数为常量的规则。
  • 你直接在 test 里调用 has_char_a("abc") 可以正常运行,是因为这个调用是运行期执行,没有要求编译期求值。

修复方案

方案1:C++20 字符串字面量模板参数(推荐)

C++20支持将字符串字面量作为模板非类型参数,可直接在编译期获取完整字符串内容:

#include <algorithm>
#include <string>
#include <iostream>
using namespace std;

template<size_t N>
struct StringLiteral {
    constexpr StringLiteral(const char (&str)[N]) {
        std::copy_n(str, N, value);
    }
    char value[N];
};

template<StringLiteral Str>
constexpr bool has_char_a()
{
    for (size_t i = 0; i < sizeof(Str.value); i++)
    {
        if (Str.value[i] == 'a') return true;
    }
    return false;
}

template<StringLiteral Str>
std::string make_string()
{
    static_assert(has_char_a<Str>(), "error");
    return std::string{ Str.value, sizeof(Str.value) - 1 };
}

void test()
{
    cout << has_char_a<"abc">() << endl;
    cout << make_string<"abc">() << endl;
}

注:C20之前std::string的构造函数不是constexpr,所以make_string不需要加constexpr修饰,C20及以上可按需添加。

方案2:调用侧预编译期求值(兼容低版本C++)

将判断逻辑移到函数调用侧,用constexpr变量提前接住编译期结果,再传入模板:

#include <string>
#include <iostream>
using namespace std;

template<int N>
constexpr bool has_char_a(const char(&s)[N])
{
    for (size_t i = 0; i < N; i++)
    {
        if (s[i] == 'a') return true;
    }
    return false;
}

template<int N, bool HasA>
std::string make_string(const char(&s)[N])
{
    static_assert(HasA, "error");
    return std::string{ s, N - 1 };
}

void test()
{
    constexpr bool has_a = has_char_a("abc");
    cout << has_a << endl;
    cout << make_string<3, has_a>("abc") << endl;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 16:15:03