检查对象是否声明为const

时间:2012-03-27 13:12:11

标签: c++ c++11 typetraits

如果对象声明为const,我想打破编译。

以下不起作用:

#include <type_traits>

struct A {

    A() : v(0)
    {
        static_assert( ! std::is_const<decltype(*this)>::value, "declared as const" );
    }

    int& AccessValue() const
    {
        return const_cast< int& >( v );
    }

    int v;
};

int main()
{
    A a1; // ok, this compiles
    const A a2; // no, this break the compilation

    a1.AccessValue() = 5; // ok
    a2.AccessValue() = 6; // OPS
}

那么,如果这种类型的对象被声明为const,有没有办法打破编译?

3 个答案:

答案 0 :(得分:3)

你走错了路。

this的类型完全由您使用它的方法的签名决定。也就是说,this始终为cv T* const类型,其中cv对应于方法的CV限定符。

因此,在构造函数中,this只是T* const


const_cast是代码气味,通常仅在处理const时使用 - 破坏旧版库...或(有时)以避免违反DRY。在新代码中,您不必使用它。

您可以选择:

  • 使AccessValue非const,因为它不是
  • i声明为mutable

我建议选择以前的解决方案。放弃private属性的句柄已经很糟糕(打破封装),也不需要违反const正确性。

答案 1 :(得分:1)

对于您的具体示例,将i变为可变将实现您的目标:

int& AccessValue() const
{
    return v;
}

mutable int v;

这来自§7.1.6.1/ 4 [dcl.type.cv]:

  

除了可以修改任何声明为mutable(7.1.1)的类成员之外,任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为。

请注意,您无法使用const对象上的指针成员修改v - n3290草稿[§5.5/ 5] [expr.mptr.oper]:

  

[注意:不可能使用指向成员的指针来引用可变成员来修改const类对象。例如,

struct S {
S() : i(0) { }
mutable int i;
};

void f()
{
const S cs;
int S::* pm = &S::i; // pm refers to mutable member S::i
cs.*pm = 88;         // ill-formed: cs is a const object
}
  

- 结束说明]

答案 2 :(得分:0)

你可以有多个变量引用同一个对象,一些是可变的,一些是const。 例如:

A a1;
const A &a2 = a1;
A * const pa = &a1;
f(a1);
....
void f(const A &a);

在您的情况下是否允许这些? 从mutable到const的转换是隐含的,反之亦然。 也许如果你举一个例子会有所帮助。

编辑:(响应修改后的代码) 使用const对象,您只能调用const成员函数。 为什么没有:

int& AccessValue()
{
    return v;
}
如果你在非const对象上调用AccessValue,那么

抱怨的编译器。