Что означает это предложение в параграфе §3.2/2 стандарта C++11?

Предложение является частью параграфа §3.2/2:

Переменная, имя которой появляется как потенциально вычисляемое выражение, используется odr, если это не объект, который удовлетворяет требованиям для появления в постоянном выражении (5.19) и немедленно применяется преобразование lvalue-to-rvalue (4.1). .

Что именно означает предложение, выделенное жирным шрифтом выше?

Изменить:

Ответ на вопрос, дубликатом которого считается этот, не говорит ничего, что могло бы ответить на мой вопрос.


person Wake up Brazil    schedule 06.05.2014    source источник


Ответы (1)


Это означает, что когда вы используете константу как константу, это точно так же, как если бы вы действительно использовали константу.

struct S {
  static const int i = 0;
};
int main() {
  return S::i;
}

Хотя у S::i есть инициализатор, у него нет определения, но текст в вашем вопросе делает специальное исключение для подобных случаев, когда S::i доступен только для его значения. В этом случае определение не требуется.

С другой стороны, другие варианты использования требуют определения:

struct S {
  static const int i = 0;
};
int f(const int &i) {
  return i;
}
int main() {
  return f(S::i);
}

Эта программа недействительна и принимается некоторыми реализациями, но отвергается другими. Вызов f требует существования фактического определения S::i, хотя, если f будет встроен, отсутствие определения может остаться незамеченным.

В моей системе, если скомпилировать и связать вторую программу без оптимизации, я получаю:

$ g++ test2.cc -o test2
/tmp/ccdEsfxs.o:test2.cc:function main: error: undefined reference to 'S::i'
collect2: error: ld returned 1 exit status

Чтобы заставить его работать, необходимо предоставить определение, например:

struct S {
  static const int i = 0;
};
const int S::i;
person Community    schedule 06.05.2014
comment
Как бы вы связали фразу преобразования lvalue-to-rvalue сразу после применения к вашему первому примеру? - person Wake up Brazil; 06.05.2014
comment
Что вы имеете в виду, говоря, что у него нет определения? - person 0x499602D2; 06.05.2014
comment
@WakeupBrazil S::i — это lvalue, оно используется в операторе return в функции, возвращающей int. В этом случае значение lvalue необходимо преобразовать (и оно преобразуется) в значение r. (Не факт, что он сам по себе используется в операторе return: в функции, возвращающей int &, преобразование lvalue-to-rvalue не будет применяться.) - person ; 06.05.2014
comment
@ 0x499602D2 Что у него нет определения. Я обновлю, чтобы указать ошибку компоновщика, которую я могу получить для этого, что, надеюсь, поможет прояснить ситуацию. - person ; 06.05.2014
comment
@hvd Я говорю о немедленном применении? Что это обозначает? - person Wake up Brazil; 06.05.2014
comment
@WakeupBrazil В моем втором примере lvalue S::i передается в f, и только внутри f применяется преобразование lvalue в rvalue. Это означает, что он не применяется немедленно. - person ; 06.05.2014
comment
@hvd Но как можно сделать вывод о том, что вы говорите, из фразы, выделенной в моем вопросе? - person Wake up Brazil; 06.05.2014
comment
@WakeupBrazil Я не понимаю, как вы можете читать это по-другому, поэтому я не знаю, как на это ответить. Слово немедленно просто используется в его повседневном английском значении. Не могли бы вы пояснить, почему, по вашему мнению, это немедленно применяется во втором примере или почему вы не думаете, что оно немедленно применяется в моем первом примере? - person ; 06.05.2014
comment
Может быть, я не очень ясно выразился. В стандарте есть следующее предложение: переменная, имя которой появляется как потенциально оцениваемое выражение, используется odr, если только она не является объектом, который удовлетворяет требованиям для появления в постоянном выражении (5.19) и преобразования lvalue-to-rvalue (4.1) применяется немедленно. Затем вы сказали, что это сделает ваш первый фрагмент легальным. Мой вопрос: должен ли я догадаться об этом, просто прочитав Стандарт? - person Wake up Brazil; 06.05.2014
comment
@WakeupBrazil А, хорошо, это я понимаю. Нет, стандарт написан таким образом, чтобы быть как можно более однозначным (чтобы каждый компилятор C++ реализовывал один и тот же язык), а не быть настолько простым для чтения, насколько это возможно. Я согласен, что трудно понять, что под этим подразумевается, если вы еще не знаете (или не знаете). - person ; 06.05.2014