BЈовић
BЈовић

Reputation: 64293

Check if object declared const

I would like to break the compilation if the object is declared const.

The following doesn't work :

#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
}

So, is there a way to break the compilation if an object of this type is declared const?

Upvotes: 2

Views: 1997

Answers (3)

Matthieu M.
Matthieu M.

Reputation: 300439

You are heading the wrong way.

The type of this is purely dictacted by the signature of the method in which you use it. That is, this is always of type cv T* const where cv corresponds to the CV qualifiers of the method.

Therefore, in a constructor, this is just T* const.


const_cast is a code smell, normally only of use when dealing with const-broken legacy libraries... or (sometimes) to avoid violating DRY. In new code, you should not have to use it.

You are left with a choice:

  • make AccessValue non-const, since it is not
  • declare i as being mutable.

I would advise choosing the former solution. Giving away a handle to a private attribute is bad already (breaks encapsulation), no need to violate const correctness as well.

Upvotes: 4

Mat
Mat

Reputation: 206919

For your specific example, making i mutable would achieve your goal:

int& AccessValue() const
{
    return v;
}

mutable int v;

This is from §7.1.6.1/4 [dcl.type.cv]:

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.

Note that you can't modify v using a pointer-to-member on a const object - §5.5/5 of n3290 draft [expr.mptr.oper]:

[ Note: it is not possible to use a pointer to member that refers to a mutable member to modify a const class object. For example,

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
}

— end note ]

Upvotes: 1

Marius
Marius

Reputation: 837

you can have multiple variables referring to the same object, some mutable and some const. For example:

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

should these be allowed in your case? Conversion from mutable to const is implicit the reverse is not. Maybe if you give an example will help.

EDIT: (in response to modified code) with a const object you can call only const member function. why not have:

int& AccessValue()
{
    return v;
}

an the compiler with complain if you call AccessValue on a non const object.

Upvotes: 0

Related Questions