Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create pointer-to-mutable-member?

Consider the following code:

struct Foo
{
    mutable int m;

    template<int Foo::* member> 
    void change_member() const {
        this->*member = 12; // Error: you cannot assign to a variable that is const
    }

    void g() const {
    change_member<&Foo::m>();
    }
};

Compiler generates an error message. The thing is that the member m is mutable therefore it is allowed to change m. But the function signature hides mutable declaration.

How to decalre pointer-to-mutable-member to compile this code? If it is impossible please link to Standard C++.

like image 598
Alexey Malistov Avatar asked Apr 20 '10 12:04

Alexey Malistov


People also ask

What is a mutable member in c++?

Mutable data members are those members whose values can be changed in runtime even if the object is of constant type. It is just opposite to constant. Sometimes logic required to use only one or two data member as a variable and another one as a constant to handle the data.

Why use mutable in c++?

The keyword mutable is mainly used to allow a particular data member of const object to be modified. When we declare a function as const, the this pointer passed to function becomes const. Adding mutable to a variable allows a const pointer to change members.

Is set in c++ mutable?

The C++ Standard does not specify whether the iterator of a set container (type set<T>:: iterator) is a mutable or immutable iterator. As a result, popular compilers and their Standard libraries provide different implementations of the set iterator.

What is the role of mutable storage class specifier?

The mutable storage class specifier is used only on a class data member to make it modifiable even though the member is part of an object declared as const . You cannot use the mutable specifier with names declared as static or const , or reference members.


1 Answers

This code is ill-formed according to C++ Standard 5.5/5:

The restrictions on cv-qualification, and the manner in which the cv-qualifiers of the operands are combined to produce the cv-qualifiers of the result, are the same as the rules for E1.E2 given in 5.2.5. [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 {
  mutable int i;
};
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

]

You could use wrapper class to workaround this problem as follows:

template<typename T> struct mutable_wrapper { mutable T value; };

struct Foo
{
    mutable_wrapper<int> m;

    template<mutable_wrapper<int> Foo::* member> 
    void change_member() const {
        (this->*member).value = 12; // no error
    }

    void g() const {
    change_member<&Foo::m>();
    }
};

But I think you should consider redesign your code.

like image 87
Kirill V. Lyadvinsky Avatar answered Oct 04 '22 16:10

Kirill V. Lyadvinsky