2014-09-28 1 views
1

Стандарт обеспечивает следующее примечание:Мутация изменяемых данных-член через указатель на член

[Примечание: это не представляется возможным использовать указатель на элемент, который ссылается на изменяемый член изменить объект класса const. Например,

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 примечание]

Но мы можем использовать только объектно-выражение для изменения константного объекта, имеющий элемент mutale данных.

#include <iostream> 
struct A 
{ 
    A(){ } 
    mutable int a; 
}; 
const A a; 

int main() 
{ 
    a.a = 4; 
    std::cout << a.a; //4 
} 

DEMO

Но ISO/IEC Derictive говорит

Примечания и примеры интегрированных в тексте документа должны быть использоваться только для предоставления дополнительной информации, предназначенной для оказания помощи понимания или использования документа. Они не должны содержать требования («должны», см 3.3.1 и таблицу Н.1) или любую информацию считается необходимым для использования документа [...]

Что означает примечание я обеспечиваю в начале моего Q не является требованием.

Я ищу нормативное требование, исключающее такое использование.

ответ

1

Непосредственно перед тем, что внимание вы найдете следующее:

Ограничения на сорте-Quali фантастическом катионом, и способ, в котором CV-Quali фи ERS операндов объединяются для получения резюме-Quali фи ЕРО результата , такие же, как правила E1.E2 приведены в 5.2.5

Перейти к 5.2.5, и вы увидите это:

Если E2 не является статическим членом данных и t ype of E1 является «cq1 vq1 X», а тип E2 - «cq2 vq2 T», выражение обозначает именованный элемент объекта, обозначенный первым выражением. Если E1 - значение l, то E1.E2 является lзначением; в противном случае E1.E2 является значением x. Пусть обозначение vq12 означает «объединение» vq1 и vq2; то есть, если vq1 или vq2 является изменчивым, то vq12 является изменчивым. Аналогично, пусть обозначение cq12 обозначает «объединение» cq1 и cq2; то есть , если cq1 или cq2 const, то cq12 является константой. Если E2 объявлен как изменяемый элемент, то тип E1.E2 является «vq12 T». Если E2 не является изменяемым элементом, то тип E1.E2 является «cq12 vq12 T».

Объединение константных классификаторов в cs.*pm является const, исключение для mutable членов не применяется к указателям.

Это легче понять, если вы считаете, что спецификаторы класса хранения не являются частью этого типа, поэтому как компилятор сможет отличить mutable и не mutable указателей?

struct S; 

void f(const S& s, int S::* pm) 
{ 
    s.*pm = 1; // How do I know if pm points to a mutable member? S isn't even defined! 
} 

Проще говоря, нет такого понятия, как указатель на mutable члена, так же, как не существует такого понятия, как указатель на static члена, класс хранения заостренной Type неизвестно (тип может только быть квалифицированным const и/или volatile).

+1

Не ясно. Вы правы в объединении спецификаторов const в cs. * Pm is const. Но если E2 объявлен как изменяемый член, то тип E1.E2 является «vq12 T» _. Это означает, что cs. * Pm не является константным. – 2014-09-28 09:26:52

+1

E2 в этом случае не является изменяемым членом, это * указатель * для члена, который может быть или не быть «изменчивым», эта информация уже потеряна. – user657267

+0

Стандарт в конце 5.5/2: _ Результатом является объект или функция типа, указанного вторым операндом_, что в нашем случае это просто 'int'. Это то, что вы имеете в виду? – 2014-09-28 09:44:48