Очевидно, что комментарий во фрагменте был неверным, так как переменная S::x
используется в выражении &S::x
.
И затем это выражение отбрасывается на битовый пол,&S::x;
не используется ODR.Однажды вариант [basic.def.odr]
параграфа 3 гласит (выделено жирным шрифтом):
Переменная x
, имя которой выглядит как потенциально оцениваемое выражение ex
, является odr-используется ex
, если применение преобразования lvalue-to-rvalue в x
не приводит к константному выражению, которое не вызывает никаких нетривиальных функций и, если x
является объектом, ex
является элементом набора потенциальных результатов выражения e
, где либо преобразование lvalue-в-значение применяется к e
, либо e
является выражением отброшенного значения .
Раздел [expr]
, параграф 11, охватывает концепцию выражения отбрасываемого значения:
В некоторых контекстах выражение появляется только для его побочных эффектов.Такое выражение называется выражением отброшенного значения .Выражение вычисляется и его значение отбрасывается.Стандартные преобразования массива в указатель и функции в указатель не применяются.Преобразование lvalue-to-rvalue применяется тогда и только тогда, когда выражение является glvalue типа volatile-квалифицированным и является одним из следующих:
- (выражение), где выражение является одним из следующихвыражения,
- id-выражение,
- подписка,
- доступ к члену класса,
- косвенное указание,
- операция указателя на член,
- условное выражение, где оба и третий операнд являются одним из этих выражений, или
- выражение запятой, где правый операнд является одним из этих выражений.
Оператор &S::x;
является выражением отбрасываемого значения, которое не требует преобразования lvalue в rvalue, поэтому преобразовывать нечего.С таким же успехом оператор может не существовать и, следовательно, не существует в том, что касается использования ODR.
Этот показатель можно изменить, указав S::x
как volatile
, а не const
,и пытаясь сбросить S::x
на битовый этаж:
struct S { static volatile int x; };
void f() { S::x; } // This discarded-value expression does odr-use S::x
int main(){
f();
}
Выше компилируется (но с предупреждением об отброшенном выражении) с компилятором / компоновщиком GNU C ++ с использованием --std=c++03
, но не компилируется /ссылка с использованием --std=c++11
или выше.C ++ 11 добавил совсем немного о работе абстрактной машины C ++.Несмотря на то, что S::x;
остается выражением отброшенного значения, для того, чтобы S::x
теперь было энергозависимым, требуется, чтобы компилятор применил преобразование lvalue-в-значение перед сбросом результата в битовый пол.
Изменение S::x
в приведенном выше к &S::x
и программа снова компилируется (но еще раз с предупреждением об отброшенном выражении).Несмотря на то, что S::x
является изменчивым, это не адрес.