如何在断言中“强制”使用const访问器?

时间:2018-07-26 16:00:38

标签: c++ const

我的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;
}

Code on Coliru

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

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

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


虽然我有大约一种方法可以实现此目的,但是我发现它很不干净,我宁愿在这种情况下使用更常规的方法:const_cast基础对象。

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

1 个答案:

答案 0 :(得分:1)

由于c不是const:

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 :: as_const产生歧义,这是因为std名称空间中的对象具有ADL。