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

能否为std::array实现编译期边界检查:常量索引越界报错,变量索引正常?

问题描述

考虑如下C++类:

template <int N>
class A {
private:
  std::array<double, N> m_vs = {};
public:
  int size() {return N;}
  void set_value(double d, int n=0) {m_vs[n] = d;}
  double get_value(int n=0) {return m_vs[n];}
};

假设我们实例化了 a = A<10>(),希望调用 a.set_value(1, 20) 时编译器抛出错误(已知该索引越界),但调用 a.set_value(1, i) 时不报错(i可能为合法索引)。请问是否可以实现该行为?


实现方案

可以实现,核心是区分编译期常量索引和运行期变量索引:对编译期常量做静态检查,运行期变量则保留原逻辑(也可按需添加运行时断言)。以下是两种常用实现方式:

方式一:重载模板版本的成员函数

为set_value和get_value新增模板重载,专门处理编译期整数常量索引,通过static_assert在编译阶段拦截越界:

#include <array>
#include <stdexcept>

template <int N>
class A {
private:
  std::array<double, N> m_vs = {};
public:
  int size() {return N;}

  // 处理运行期变量索引的版本
  void set_value(double d, int n=0) {
    // 可选:添加运行时检查,避免运行期越界崩溃
    if (n < 0 || n >= N) {
      throw std::out_of_range("Index out of bounds");
    }
    m_vs[n] = d;
  }

  // 处理编译期常量索引的版本
  template <int Idx>
  void set_value(double d) {
    static_assert(Idx >= 0 && Idx < N, "Compile-time index out of bounds");
    m_vs[Idx] = d;
  }

  // get_value同理实现重载
  double get_value(int n=0) {
    if (n < 0 || n >= N) {
      throw std::out_of_range("Index out of bounds");
    }
    return m_vs[n];
  }

  template <int Idx>
  double get_value() {
    static_assert(Idx >= 0 && Idx < N, "Compile-time index out of bounds");
    return m_vs[Idx];
  }
};

使用示例:

  • 编译期常量索引:调用模板版本 a.set_value<20>(1),编译器会触发static_assert直接报错;
  • 运行期变量索引:调用普通版本 a.set_value(1, i),仅执行运行期逻辑(可选择去掉运行时检查完全保留原行为)。

方式二:C++20 constexpr上下文判断(无需重载)

利用C++20引入的std::is_constant_evaluated(),直接在原函数内判断当前是否处于编译期常量求值上下文,针对性执行检查:

#include <array>
#include <type_traits>

template <int N>
class A {
private:
  std::array<double, N> m_vs = {};
public:
  int size() {return N;}

  void set_value(double d, int n=0) {
    // 若n是编译期常量,触发静态检查
    if constexpr (std::is_constant_evaluated()) {
      static_assert(n >= 0 && n < N, "Compile-time index out of bounds");
    }
    // 运行期逻辑(可选添加运行时断言)
    m_vs[n] = d;
  }

  double get_value(int n=0) {
    if constexpr (std::is_constant_evaluated()) {
      static_assert(n >= 0 && n < N, "Compile-time index out of bounds");
    }
    return m_vs[n];
  }
};

这种方式无需重载函数:

  • 传入20这类字面量时,std::is_constant_evaluated()返回true,触发static_assert编译报错;
  • 传入变量i时,该值无法在编译期确定,跳过静态检查直接执行运行期逻辑。

注意:std::is_constant_evaluated()的判断依赖编译器对常量上下文的识别,复杂场景下需注意边界,但直接传入字面量的场景完全适用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:52:52