如何在断言中'force' const 访问器的使用?

How can I 'force' the use of the const accessor in the assert?

本文关键字:访问 const force 断言      更新时间:2023-10-16

我的google fu不允许我找到任何关于这方面的信息,所以我在这里询问

我已经通过cppcheck运行了我的c++代码,它报告说assert调用中的一些代码可能有潜在的副作用。我以较小的规模复制了这个问题:

struct Obj
{
int* myInt;
Obj() : myInt( new int(3) ) {}
~Obj() { delete myInt; }
const int* getInt() const { return myInt; }
};
struct C
{
Obj* myObj;
C() : myObj( new Obj() ) {}
~C() { delete myObj; }
const Obj* getObj() const { std::cout << "const" ; return myObj; }
Obj* getObj()       { std::cout << "non const" ; return myObj; }
};
int main()
{
C c;
assert( c.getObj()->getInt() ); // Outputs "non const"
return 0;
}

(Coliru代码(

cppcheck是对的,这里:使用的getObj()方法不是const方法,而是非常量方法。

目标是1(满足cppcheck,2(确保这些断言中没有副作用。

我如何告诉编译器使用const版本而不是非常量getter?


我有一种方法可以实现这一点,但我发现它非常不干净,我宁愿在这种情况下使用更传统的方法:const_cast基本对象。

assert( const_cast<const C&>(c).getObj()->getInt() );

由于c不是常量:

C c;
c.getObj();

执行非常量版本。在C++17中有一个std::as_const(),您可以使用它:

assert( std::as_const(c).getObj()->getInt() );

这比你建议的略好:

assert( const_cast<const C&>(c).getObj()->getInt() );

如果c++17不可用,您可以实现自己的as_const,并在断言语句:

template <class T>
const T & as_const(T& obj) 
{
return obj;
}
template <class T>
void as_const(const T&& obj) = delete;

并使用它:

assert(::as_const(c).getObj()->getInt() );

必须添加::前缀,以避免由于std命名空间中对象的ADL而与std::as_const产生歧义。