C++ 检查对象是否声明为常量

C++ 检查对象是否声明为常量,c++,c++11,typetraits,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 con

如果对象声明为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
}
#包括
结构A{
A():v(0)
{
静态断言(!std::is_const::value,“声明为const”);
}
int&AccessValue()常量
{
返回常量cast(v);
}
INTV;
};
int main()
{
a1;//好的,这个编译
const A a2;//不,这会中断编译
a1.AccessValue()=5;//确定
a2.AccessValue()=6;//操作
}

那么,如果这种类型的对象被声明为常量,有没有办法中断编译?

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

A a1;
const A &a2 = a1;
A * const pa = &a1;
f(a1);
....
void f(const A &a);
在你的情况下应该允许这些吗? 从可变到常量的转换是隐式的,反之亦然。 也许你举个例子会有所帮助

编辑:(响应修改后的代码) 对于常量对象,只能调用常量成员函数。 为何不:

int& AccessValue()
{
    return v;
}

如果在非常量对象上调用AccessValue,编译器会发出抱怨。

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

A a1;
const A &a2 = a1;
A * const pa = &a1;
f(a1);
....
void f(const A &a);
在你的情况下应该允许这些吗? 从可变到常量的转换是隐式的,反之亦然。 也许你举个例子会有所帮助

编辑:(响应修改后的代码) 对于常量对象,只能调用常量成员函数。 为何不:

int& AccessValue()
{
    return v;
}

如果在非常量对象上调用AccessValue,编译器会发出抱怨。

对于您的特定示例,使
i
可变将实现您的目标:

int& AccessValue() const
{
    return v;
}

mutable int v;
这来自§7.1.6.1/4[dcl.type.cv]:

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

请注意,您不能使用指向常量对象上成员的指针修改
v
——n3290草稿[expr.mptr.oper]的§5.5/5:

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

-[完注]


对于您的特定示例,使
i
可变将实现您的目标:

int& AccessValue() const
{
    return v;
}

mutable int v;
这来自§7.1.6.1/4[dcl.type.cv]:

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

请注意,您不能使用指向常量对象上成员的指针修改
v
——n3290草稿[expr.mptr.oper]的§5.5/5:

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

-[完注]


你走错方向了

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

因此,在构造函数中,
这个
就是
T*const


const\u cast
是一种代码气味,通常仅在处理
const
损坏的旧库时使用。。。或者(有时)为了避免违反干法。在新代码中,您不必使用它

您还有一个选择:

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

我建议选择前者。将句柄传递给
private
属性已经很糟糕了(破坏了封装),也不需要违反
const
的正确性。

您走错了方向

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

因此,在构造函数中,
这个
就是
T*const


const\u cast
是一种代码气味,通常仅在处理
const
损坏的旧库时使用。。。或者(有时)为了避免违反干法。在新代码中,您不必使用它

您还有一个选择:

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

我建议选择前者。给
private
属性一个句柄已经不好了(破坏了封装),也不需要违反
const
的正确性。

我怀疑这是可能的。你想实现什么?如果有人得到一个
const a
,但不应该得到,编译器最终会给出基本相同的错误(声明为const),所以你不需要检查这些东西。@AlexandreC。除非对象被声明为非常量,否则可以使用常量转换从常量引用更改为非常量引用。我需要使用const_cast,但想阻止人们声明这种类型的对象const@VJovic如果可能的话,我想编译器已经检查过了,因为这是在
const\u cast
@VJovic之前要做的一个非常有用和明显的诊断:您可能应该重新调整您的工作方向,以避免需要
const\u cast
。也就是说,更好的问题是:为什么需要
const\u cast
?如何避免使用
const\u cast
?我怀疑这是可能的。你想实现什么?如果有人得到一个
const a
,但不应该得到,编译器最终会给出基本相同的错误(声明为const),所以你不需要检查这些东西。@AlexandreC。除非对象是dec,否则使用const_cast将常量引用更改为非常量引用是不合适的