2010-04-20 6 views
5

Рассмотрим следующий код:Как создать указатель-to-mutable-member?

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. Но подпись функции скрывает изменчивое объявление.

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

ответ

8

Этот код плохо формируется в соответствии с стандартом 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>(); 
    } 
}; 

Но я думаю, вы должны рассмотреть перепроектировать код.

+0

Очень хорошо .. Обходным решением является совершенный! –