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

如何测试const成员函数?实现无需注释测试代码的编译验证

问题:如何测试const成员函数?

目标

对const下标运算符进行单元测试并通过测试。即能否通过让编译器抛出错误来验证功能成功,同时无需注释该测试代码,以保证其余测试可正常编译?

尝试方案

我的思路是,若检测到is_const<>::value为true,则抛出异常,让单元测试捕获该异常,以此证明无法修改下标索引处元素的值,从而使测试“通过”。

我的const下标运算符定义

#include <type_traits>

// operator [] const
template <typename T>                               
typename Vector<T>::const_reference
Vector<T>::operator[](size_t index) const {
    if (size_ <= index || index < 0) {
        throw std::out_of_range("Index out of range.");
    }
    if constexpr(std::is_const<std::decltype(*this)>::value) {
        throw std::runtime_error("Cannot modify elements of a const Vector.");
    }
    return array_[index];
}

我的单元测试代码

TEST(SubScriptConst) {
    const Vector<int> myVecConst = {0,1,2,3,4,5,6,7,8};
    try {
        myVecConst[2] = 4; // This will throw an exception?
    } 
    catch (const std::exception& ex) {
        std::cout << "SUCCESS | Caught exception: " << ex.what() << std::endl;
    }
    CHECK_EQUAL(myVecConst[2], 2);
}

明显问题

该方案无法运行。我知道这是因为对C++语言理解不足。我的推测是编译器会在代码执行前检查const对象的赋值操作并报错。我希望能将try块放在#ifdef测试宏中,仅在测试时启用,非测试时仍让编译器抛出错误。


解决方案

核心问题分析

你当前的思路存在本质错误:const成员函数返回const_reference时,myVecConst[2] = 4是编译期错误,根本到不了运行时抛异常的阶段——编译器会直接阻止这种修改const对象的行为,所以你的try-catch完全没机会执行。

而且你在const版operator[]里加的if constexpr判断也是多余的:*this在const成员函数里本身就是const类型,这个判断永远为true,会导致每次调用const下标运算符都抛异常,这显然不符合预期(const下标应该允许读取,只是禁止修改)。

正确的测试方式

要验证const下标运算符的正确性,分两部分:

  1. 验证读取功能正常:这部分就是你已有的CHECK_EQUAL(myVecConst[2], 2);,直接测读取值即可。
  2. 验证无法修改:这部分需要在编译期验证,而不是运行时。可以通过以下方式实现:

编译期验证方案(无需注释代码)

借助C++的SFINAE特性,编写一个检测是否能赋值的辅助模板,通过静态断言验证结果:

#include <type_traits>

// 辅助模板:检测类型是否支持赋值操作
template<typename T, typename = void>
struct is_assignable : std::false_type {};

template<typename T>
struct is_assignable<T, std::void_t<decltype(std::declval<T>() = std::declval<T>())>> : std::true_type {};

TEST(SubScriptConst_CannotModify) {
    const Vector<int> myVecConst = {0,1,2,3,4,5,6,7,8};
    // 编译期验证:const下标返回值不可赋值
    static_assert(!is_assignable<decltype(myVecConst[2])>::value,
                  "Const Vector's operator[] should return non-assignable const reference");
    
    // 读取功能验证
    CHECK_EQUAL(myVecConst[2], 2);
}

这种方式完全在编译期完成验证,不需要注释任何代码,且非测试环境下如果有人尝试修改const Vector的元素,编译器依然会直接报错。

修正你的const下标运算符

首先要删掉多余的if constexpr判断,同时移除冗余的index <0判断(size_t是无符号类型,永远不会小于0):

#include <type_traits>

// operator [] const
template <typename T>                               
typename Vector<T>::const_reference
Vector<T>::operator[](size_t index) const {
    if (index >= size_) {
        throw std::out_of_range("Index out of range.");
    }
    return array_[index];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:07:39