Can you properly test a const member function If you include exception safety inside that function without having to comment it out after?

huangapple go评论68阅读模式
英文:

Can you properly test a const member function If you include exception safety inside that function without having to comment it out after?

问题

以下是您要翻译的内容:

问题
如何测试一个常量成员函数?

目标:

单元测试一个常量下标运算符并获得通过的测试。换句话说,我是否可以避免编写一个测试;让编译器抛出错误来证明成功,然后避免需要注释掉测试以允许其余测试正确编译?

我的尝试:
我的推理是,如果我测试is_const<>::value并且为真,我可以抛出一个异常,该异常将被我的单元测试捕获,并允许测试“通过”,因为未能更改下标索引位置的元素值。

我的常量下标定义

#include &lt;type_traits&gt;

// operator [] const

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

我的单元测试

TEST(SubScriptConst) {
    const Vector&lt;int&gt; myVecConst = {0,1,2,3,4,5,6,7,8};
    try {
        myVecConst[2] = 4; // 这将抛出一个异常?
    } 
    catch (const std::exception&amp; ex) {
        std::cout &lt;&lt; &quot;成功 | 捕获到异常:&quot; &lt;&lt; ex.what() &lt;&lt; std::endl;
    }
    CHECK_EQUAL(myVecConst[2], 2);
}

显而易见。
它不起作用。我知道这是因为我对语言的理解不够。我的假设是编译器在代码执行之前检查常量的值赋值并报错。如果可能的话,我将把try块放在一个用于测试的宏#ifdef中,仍然允许编译器在不测试时抛出错误。

英文:

Question
How does one test a const member function?

Goal:

Unit test a const subscript operator and get a passing test. In other words can I avoid writing a test; have a compiler throw an error to prove success, then avoid the need to comment the test out to allow proper compilation for the remainder of the tests?

My Attempts:
My reasoning was if I test for is_const<>::value and is true I can throw an exception that would be caught by my unit test and allow the test to "Pass" do to failure to change value of element at location of subscript index.

my const subscript definition

   #include &lt;type_traits&gt;

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

my UnitTest

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

The obvious.
It does not work. I know its because of my lack of understanding the language. My assumptions are the compiler is checking the value assignment of a const before the code is executed and gives error. If I am able to I will be placing the try block inside a MACRO #ifdef for testing only and still allow the compiler to throw error when not testing.

答案1

得分: 1

如果一个类的成员函数被声明为const,那么它不能修改任何类数据成员,除非这些类数据成员被声明为mutable

这种const行为是由编译器强制执行的,而不是由C++运行时执行的。因此,如果有人尝试在const成员函数中修改非mutable数据成员,那将是编译时错误,而不是运行时错误。因此,您可以跳过编写这种测试用例。

以下是C++标准中的一些相关摘录:

[注 1:因此,在const成员函数中,调用该函数的对象是通过const访问路径访问的。 —结束注释]

int s::f() const { return a; }

s::h的主体中的a++是非法的,因为它试图修改调用s::h()的对象(部分)。这在const成员函数中是不允许的,因为this是一个指向const的指针;也就是说,*this具有const类型。

英文:

If a class member function declered as const then it can't modify any class data members except the class data members which are declered mutable.

This const behavior is enforced by compiler and not the C++ runtime. So if someone will try to modify a non-mutable data member in const member function then it will be a compile time error and not a runtime error. So you can skip writing such test cases.

Following are some related excerpts from in C++ standard:

>[Note 1: Thus in a const member function, the object for which the function is called is accessed through a const
access path. —end note]

>
>
>int s::f() const { return a; }
>
>The a++ in the body of s::h is ill-formed because it tries to modify (a part of) the object for which s::h() is called.
>
>This is not allowed in a const member function because this is a pointer to const; that is, *this has const type.

huangapple
  • 本文由 发表于 2023年2月27日 11:41:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75576592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定