Как создать указатель на изменяемый член? - PullRequest
5 голосов
/ 20 апреля 2010

Рассмотрим следующий код:

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>();
    }
};

Компилятор генерирует сообщение об ошибке. Дело в том, что член m является изменяемым, поэтому ему разрешено изменять m. Но подпись функции скрывает изменяемое объявление.

Как декалировать указатель на изменяемый член для компиляции этого кода? Если это невозможно, пожалуйста, обратитесь к Стандарту C ++.

1 Ответ

8 голосов
/ 20 апреля 2010

Этот код некорректен в соответствии со стандартом C ++ 5.5 / 5:

Ограничения на cv-квалификацию, и каким образом cv-квалификаторы операндов объединены, чтобы произвести cv-квалификаторы результата, такие же, как правила для E1.E2 приведены в 5.2.5. [Заметка: невозможно использовать указатель на член, который ссылается на изменяемый член для изменения класса const объект. Например,

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

]

Вы можете использовать класс-оболочку для решения этой проблемы следующим образом:

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>();
    }
};

Но я думаю, вам стоит подумать о редизайне своего кода.

...