8 Expressions [expr]

8.2 Postfix expressions [expr.post]

[ Маркер следующего за в , , или может быть продуктом заменяя маркер на два следующих друг за другом маркеров ( ). ]Note: > type-id dynamic_­caststatic_­cast reinterpret_­castconst_­cast >> >[temp.names]end note

8.2.1 Subscripting [expr.sub]

Постфиксное выражение, за которым следует выражение в квадратных скобках, является постфиксным выражением. Одно из выражений должно быть значением glvalue типа «array of T» или prvalue типа «указатель на T», а другое должно быть prvalue перечисления без области действия или целочисленного типа. Результат имеет тип «T». Тип «T» должен быть полностью определенным типом объекта.66 Выражение E1[E2] идентично (по определению) *((E1)+(E2)) [ Note: см. [expr.unary] И [expr.add] для деталей * и + и [dcl.array] для деталей массивов. ], за исключением того, что в случае операнда массива результатом является lvalue, если этот операнд является lvalue, и xvalue в противном случае. Выражение упорядочивается перед выражением .end note E1 E2

braced-init-listНе должен использоваться с встроенным индексом оператора.

Это верно , даже если индекс оператор используется в общих идиомы: &x[0].

8.2.2 Function call [expr.call]

Вызов функции - это постфиксное выражение, за которым следуют круглые скобки, содержащие, возможно, пустой, разделенный запятыми список, initializer-clauses который составляет аргументы функции. Постфиксное выражение должно иметь тип функции или тип указателя функции. Для вызова функции, не являющейся членом, или статической функции-члена, постфиксное выражение должно быть либо lvalue, которое относится к функции (в этом случае function-to-pointer standard conversion подавляется в постфиксном выражении), либо оно должно иметь тип указателя функции. Вызов функции через выражение, тип функции которого отличается от типа функции определения вызываемой функции, приводит к неопределенному поведению ([dcl.link]). Для вызова нестатической функции-члена постфиксное выражение должно быть неявным ([class.mfct.non-static], [class.static]) или явным class member access , id-expressionкоторое является именем члена функции или pointer-to-member expression выбором члена функции; вызов осуществляется как член объекта класса, на который ссылается выражение объекта. В случае неявного доступа к члену класса подразумеваемый объект - это тот, на который указывает this. [ Note: Вызов функции-члена формы f() интерпретируется как (*this).f() (см. [class.mfct.non-static]). ] Если используется имя функции или функции-члена, имя может быть таким , и в этом случае соответствующая функция должна быть выбрана в соответствии с правилами в . Если выбранная функция не виртуальная или если в выражении доступа к члену класса указано a , эта функция вызывается. В противном случае вызывается его динамический тип выражения объекта; такой вызов называется . [ Динамический тип - это тип объекта, на который ссылается текущее значение выражения объекта. описывает поведение вызовов виртуальных функций, когда выражение объекта относится к объекту, находящемуся в процессе строительства или уничтожения. ]end noteoverloaded [over.match]id-expressionqualified-id final overrider virtual function callNote: [class.cdtor] end note

[ Note: Если используется имя функции или функции-члена, name lookup но не найдено объявление с таким именем, программа имеет неправильный формат. При таком вызове неявно не объявляется никакая функция. ]end note

Если postfix-expressionобозначает destructorтип выражения вызова функции void; в противном случае тип выражения вызова функции - это тип возвращаемого значения статически выбранной функции (т. е. игнорирование virtual ключевого слова), даже если тип фактически вызываемой функции отличается. Этот возвращаемый тип должен быть типом объекта, ссылочным типом или cv void.

Когда функция вызывается, каждый параметр ([dcl.fct]) должен быть инициализирован ([dcl.init], [class.copy], [class.ctor]) с соответствующим аргументом. Если функция является нестатической функцией-членом, this parameter объект функции должен быть инициализирован указателем на объект вызова, преобразованным, как если бы с помощью explicit type conversion. [ Note: Для этого преобразования нет проверки доступа или неоднозначности; проверка доступа и устранение неоднозначности выполняются как часть (возможно, неявного) оператора доступа к членам класса. См [class.member.lookup], [class.access.base]и [expr.ref]. ] При вызове функции параметры, имеющие объектный тип, должны иметь полностью определенный объектный тип. [ это по-прежнему позволяет параметру быть указателем или ссылкой на неполный тип класса. Однако это не позволяет параметру, передаваемому по значению, иметь неполный тип класса. ] Это определяется реализацией, заканчивается ли время жизни параметра, когда функция, в которой он определен, возвращается, или в конце включающего полного выражения. Инициализация и уничтожение каждого параметра происходит в контексте вызывающей функции. [ Доступ конструктора, функций преобразования или деструктора проверяется в точке вызова в вызывающей функции. Если конструктор или деструктор для параметра функции вызывает исключение, поиск обработчика начинается в области действия вызывающей функции; в частности, если вызываемая функция имеет обработчик, способный обработать исключение, этот обработчик не рассматривается. ]end noteNote: end noteExample: function-try-blockend example

postfix-expressionСеквенировали перед каждым expressionв expression-list и аргумент любого по умолчанию. Инициализация параметра, включая вычисление каждого связанного значения и побочный эффект, имеет неопределенную последовательность относительно инициализации любого другого параметра. [ Note: Все побочные эффекты оценок аргументов упорядочиваются до ввода функции (см. [intro.execution]). ] [end noteExample:

void f() {
  std::string s = "but I have heard it works even if you don't believe in it";
  s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
  assert(s == "I have heard it works only if you believe in it"); // OK
}

end example] [ Note: Если операторная функция вызывается с использованием обозначения оператора, вычисление аргументов выполняется в порядке, указанном для встроенного оператора; см [over.match.oper]. ] [end noteExample:

struct S {
  S(int);
};
int operator<<(S, int);
int i, j;
int x = S(i=1) << (i=2);
int y = operator<<(S(j=1), j=2);

После выполнения инициализации значение i равно 2 (см. [expr.shift]), Но не указано, является ли значение j 1 или 2. ]end example

Результатом вызова функции является результат операнда вычисляемой return statement в вызываемой функции (если есть), за исключением вызова виртуальной функции, если тип возвращаемого значения последнего переопределителя отличается от типа возвращаемого значения статически выбранной функции, значение, возвращаемое последним переопределителем, преобразуется в тип возвращаемого значения статически выбранной функции.

[ Функция может изменять значения своих неконстантных параметров, но эти изменения не могут повлиять на значения аргументов, за исключением случаев, когда параметр имеет ссылочный тип ( ); если ссылка относится к типу, уточненному константой , необходимо использовать для отказа от константности, чтобы изменить значение аргумента. Если параметр имеет ссылочного типа временный объект введен в случае необходимости ( , , , , ). Кроме того, можно изменять значения непостоянных объектов с помощью параметров указателя. ]Note: [dcl.ref] const_­cast const [dcl.type] [lex.literal] [lex.string] [dcl.array] [class.temporary]end note

Функцию можно объявить так, чтобы она принимала меньше аргументов (путем объявления default arguments) или большего количества аргументов (с помощью многоточия ..., или параметра функции pack ([dcl.fct])), чем количество параметров в function definition. [ Note: Это означает, что, за исключением случаев использования многоточия (...) или пакета параметров функции, параметр доступен для каждого аргумента. ]end note

Если для данного аргумента нет параметра, аргумент передается таким образом, что принимающая функция может получить значение аргумента путем вызова va_­arg. [ Note: Этот абзац не применяется к аргументам, переданным в пакет параметров функции. Пакеты параметров функции раскрываются во время создания экземпляра шаблона ([temp.variadic]), поэтому каждый такой аргумент имеет соответствующий параметр при фактическом вызове специализации шаблона функции. ] , И стандартные преобразования выполняются на выражение аргумента. Аргумент, имеющий тип, - это тип . После этих преобразований, если аргумент не имеет арифметических операций, перечисления, указателя, указателя на член или типа класса, программа имеет неправильный формат. Передача потенциально оцененного аргумента наличия нетривиального конструктора копирования, нетривиального конструктора перемещения или нетривиального деструктора без соответствующего параметра условно поддерживается семантикой, определяемой реализацией. Если аргумент имеет целочисленный или перечисляемый тип, который подчиняется , или тип с плавающей запятой, который подчиняется , значение аргумента преобразуется в повышенный тип перед вызовом. Эти рекламные акции называются . end notelvalue-to-rvalue array-to-pointer function-to-pointer cv std​::​nullptr_­t converted void* class type integral promotionsfloating-point promotion default argument promotions

Рекурсивные вызовы разрешены, за исключением main function.

Вызов функции является lvalue, если тип результата является ссылочным типом lvalue или ссылкой rvalue на тип функции, xvalue, если тип результата является ссылкой rvalue на тип объекта, и prvalue в противном случае.

8.2.3 Explicit type conversion (functional notation) [expr.type.conv]

A simple-type-specifier или, typename-specifier за которым следует необязательный аргумент в скобках expression-listили braced-init-list (инициализатор), создает значение указанного типа с учетом инициализатора. Если тип является заполнителем для выведенного типа класса, он заменяется типом возвращаемого значения функции, выбранной разрешением перегрузки class template deduction для оставшейся части этого раздела.

Если инициализатор представляет собой одиночное выражение в скобках, выражение преобразования типа эквивалентно (по определенности и, если определено по смыслу), соответствующему cast expression. Если тип равен, cv void а инициализатор есть (), выражение является значением указанного типа, которое не выполняет инициализацию. В противном случае выражение является prvalue указанного типа, объект результата которого находится direct-initialized с инициализатором. Для выражения формы T(), T не должно быть тип массива.

8.2.4 Pseudo destructor call [expr.pseudo]

Использование оператора pseudo-destructor-nameпосле точки . или стрелки -> представляет деструктор для неклассового типа, обозначенного type-nameили decltype-specifier. Результат должен использоваться только как операнд для оператора вызова функции (), и результат такого вызова имеет тип void. Единственный эффект - это оценка postfix-expressionперед точкой или стрелкой.

Левая часть оператора точки должна быть скалярного типа. Левая часть оператора стрелки должна быть указателем на скалярный тип. Этот скалярный тип является типом объекта. В cv-unqualified версия типа объекта и типа назначенного pseudo-destructor-nameдолжна быть тем же типом. Кроме того, два type-names в pseudo-destructor-nameформе a

nested-name-specifieropt type-name ::~ type-name

должен обозначать один и тот же скалярный тип (игнорируя cv-квалификацию).

8.2.5 Class member access [expr.ref]

Постфиксное выражение, за которым следует точка . или стрелка ->, необязательно, за которым следует ключевое слово template ([temp.names]), а затем следует за ним id-expression, является постфиксным выражением. Выражение постфикса перед точкой или стрелкой оценивается;67 результат этой оценки, вместе с id-expression, определяет результат всего постфиксного выражения.

Для первого варианта (точка) первым выражением должно быть значение glvalue, имеющее полный тип класса. Для второго варианта (стрелка) первое выражение должно быть prvalue, имеющим указатель на полный тип класса. Выражение E1->E2 преобразуется в эквивалентную форму (*(E1)).E2; остальная часть [expr.ref] будет адресована только первому варианту (точка).68 В любом случае он id-expressionдолжен называть члена класса или одного из его базовых классов. [ Note: Поскольку имя класса вставлено в его область действия класса (пункт [class]), имя класса также считается вложенным членом этого класса. ] [ Описывает , как имена ищутся после того , как и операторов. ]end noteNote: [basic.lookup.classref] . -> end note

Сокращение как , называется . Если это битовое поле, то это битовое поле. Тип и ценностная категория определяются следующим образом. В оставшейся части , представляет собой либо или отсутствие , и представляет собой либо или отсутствие . представляет произвольный набор cv-квалификаторов, как определено в .postfix-expression.id-expression E1.E2E1 object expression E2 E1.E2 E1.E2 [expr.ref] cq const const vq volatile volatile cv [basic.type.qualifier]

Если E2 объявлен тип «ссылка на T», то E1.E2 это lvalue; тип E1.E2 есть T. В противном случае применяется одно из следующих правил.

  • Если E2 является членом статических данных и типа E2 IS T, то E1.E2 есть именующий; выражение обозначает названный член класса. Тип E1.E2 есть T.

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

  • Если E2 это (возможно, перегруженная) функция-член, функция overload resolution используется для определения того,E1.E2 относится ли она к статической или нестатической функции-члену.

    • Если он относится к статической функции-члену и типом E2 является «функция возврата списка типов-параметров T», то E1.E2 это lvalue; выражение обозначает статическую функцию-член. Тип того E1.E2 же типа, что и E2, а именно «функция возврата списка типов параметров T».

    • В противном случае, если E1.E2 относится к нестатической функции-члену и типом E2 является «функция возврата списка типов-параметров », то это prvalue. Выражение обозначает нестатическую функцию-член. Выражение может использоваться только как левый операнд вызова функции-члена ( ). [ Любой лишний набор круглых скобок, окружающий выражение, игнорируется ( ). ] Тип - «функция возврата списка типов параметров ». cv ref-qualifieropt TE1.E2 [class.mfct]Note: [expr.prim] end note E1.E2 cv T

  • Если E2 это вложенный тип, выражение E1.E2 имеет неправильный формат.

  • Если E2 является перечислителем членов и типом E2 является T, выражение E1.E2 является значением prvalue. Тип E1.E2 есть T.

Если E2 это нестатический член данных или нестатическая функция-член, программа плохо сформирована, если класс, который E2 является непосредственно членом, является неоднозначным base ([class.member.lookup]) класса именования ([class.access.base]) из E2. [ Note: Программа также плохо сформирована, если класс именования является неоднозначным основанием типа класса выражения объекта; см [class.access.base]. ]end note

Если вычисляется выражение доступа к члену класса, оценка подвыражения происходит, даже если результат не нужен для определения значения всего постфиксного выражения, например, если id-expressionобозначает статический член.

Обратите внимание, что (*(E1)) это lvalue.

8.2.6 Increment and decrement [expr.post.incr]

Значение постфиксного ++ выражения - это значение его операнда. [ Note: Полученное значение является копией исходного значения ] Операнд должен быть изменяемым lvalue. Тип операнда должен быть арифметическим типом, отличным от полного типа объекта, или указателем на него. Значение объекта операнда изменяется путем добавления к нему. Значение вычисление выражения секвенировано перед модификацией объекта операнда. Что касается вызова функции с неопределенной последовательностью, операция postfix - это однократная оценка. [ Следовательно, вызов функции не должен вмешиваться между преобразованием lvalue-to-rvalue и побочным эффектом, связанным с любым отдельным оператором postfix ++. ] Результат - prvalue. Тип результата - это cv-неквалифицированная версия типа операнда. Если операнд является битовым полем, которое не может представлять увеличенное значение, результирующее значение битового поля определяется реализацией. См. Также и .end note cv bool 1 ++ ++ Note: end note [expr.add] [expr.ass]

Операнд постфикса -- декрементируется аналогично ++ оператору постфикса . [ Note: Для увеличения и уменьшения префикса см [expr.pre.incr]. ]end note

8.2.7 Dynamic cast [expr.dynamic.cast]

Результат выражения dynamic_­cast<T>(v) - это результат преобразования выражения v в тип T. T должен быть указателем или ссылкой на полный тип класса, или «указателем на cv void». dynamic_­cast Оператор не должен cast away constness.

Если T это тип указателя, v должно быть prvalue указателя на полный тип класса, а результатом будет prvalue типа T. Если T - ссылочный тип lvalue, v должен быть lvalue полного типа класса, а результатом будет lvalue типа, на который ссылается T. Если T это ссылочный тип rvalue, v должно быть glvalue, имеющее полный тип класса, а результатом будет значение x того типа, на который ссылается T.

Если тип v такой же Tили такой же, T за исключением того, что тип объекта класса в T более cv-квалифицирован, чем тип объекта класса в v, результат будет v (при необходимости преобразован).

Если значение v является значением нулевого указателя в случае указателя, результатом является значение нулевого указателя типа T.

Если T это «указатель на cv1 B» и v имеет тип «указатель на cv2 D», то B есть базовый класс D, результатом является указатель на уникальный B подобъект D объекта, на который указывает v. Точно так же, если T это «ссылка на cv1 B» и v имеет cv2 D такой тип , который B является базовым классом D, результатом является уникальный B подобъект D объекта, на который ссылается v.69 Как в случае указателя, так и в случае ссылки, программа плохо сформирована, если cv2 имеет более высокую квалификацию cv, чем недоступный или неоднозначный базовый класс cv1 или если он B является D. [Example:

struct B { };
struct D : B { };
void foo(D* dp) {
  B*  bp = dynamic_cast<B*>(dp);    // equivalent to B* bp = dp;
}

end example]

В противном случае v должен быть указателем или значением glvalue polymorphic type.

Если T это «указатель на cv void», то результатом является указатель на самый производный объект, на который указывает v. В противном случае применяется проверка времени выполнения, чтобы увидеть, может ли объект, на который указывает или на который ссылается, v быть преобразован в тип, на который указывает или на который ссылается T.

Если C это тип класса, на который T указывает или ссылается, проверка времени выполнения логически выполняется следующим образом:

  • Если в наиболее производном объекте, на который указывает (упоминается) v, v указывает (ссылается) на public подобъект базового класса C объекта, и если только один объект типа C является производным от подобъекта, на который указывает (ссылается) v результирующие точки (ссылается ) к этому C объекту.

  • В противном случае, если v указывает (ссылается) на public подобъект базового класса самого производного объекта, а тип самого производного объекта имеет базовый класс типа C, который является однозначным, и publicрезультат указывает (ссылается) на C подобъект самый производный объект.

  • В противном случае проверка времени выполнения fails.

Значение неудачного приведения к типу указателя - это значение нулевого указателя требуемого типа результата. Неудачное приведение к типу ссылки throws an exception на тип, который соответствует handler типу std​::​bad_­cast.

[Example:

class A { virtual void f(); };
class B { virtual void g(); };
class D : public virtual A, private B { };
void g() {
  D   d;
  B*  bp = (B*)&d;                  // cast needed to break protection
  A*  ap = &d;                      // public derivation, no cast needed
  D&  dr = dynamic_cast<D&>(*bp);   // fails
  ap = dynamic_cast<A*>(bp);        // fails
  bp = dynamic_cast<B*>(ap);        // fails
  ap = dynamic_cast<A*>(&d);        // succeeds
  bp = dynamic_cast<B*>(&d);        // ill-formed (not a runtime check)
}

class E : public D, public B { };
class F : public E, public D { };
void h() {
  F   f;
  A*  ap  = &f;                     // succeeds: finds unique A
  D*  dp  = dynamic_cast<D*>(ap);   // fails: yields null; f has two D subobjects
  E*  ep  = (E*)ap;                 // ill-formed: cast from virtual base
  E*  ep1 = dynamic_cast<E*>(ap);   // succeeds
}

end example] [ Note: [class.cdtor] описывает поведение, dynamic_­cast применяемое к строящемуся или разрушающемуся объекту. ]end note

Указанный most derived object или упомянутый by v может содержать другие B объекты в качестве базовых классов, но они игнорируются.

8.2.8 Type identification [expr.typeid]

Результатом typeid выражения является lvalue статического типа и динамического типа, или где - это класс, определяемый реализацией, публично производный от которого сохраняет поведение, описанное в . Время жизни объекта, на который указывает lvalue, продолжается до конца программы. Не определено, вызывается ли деструктор для объекта в конце программы.const std​::​type_­info const std​::​type_­info const name name std​::​type_­info [type.info]70std​::​type_­info

Когда typeid применяется к выражению glvalue, тип которого является polymorphic class типом, результат относится к std​::​type_­info объекту, представляющему тип most derived object (то есть динамический тип), на который ссылается glvalue. Если glvalue выражение получается путем применения унарную * оператора на указатель71 и указатель является null pointer value, то typeid выражение throws an exception такого типа , который будет соответствовать обработчик типа исключения.std​::​bad_­typeid

Когда typeid он применяется к выражению, отличному от glvalue типа полиморфного класса, результат относится к std​::​type_­info объекту, представляющему статический тип выражения. Lvalue-to-rvalue, array-to-pointerИ function-to-pointer конверсия не применяется к выражению. Если выражение является prvalue, temporary materialization conversion применяется. Выражение - это unevaluated operand.

Когда typeid применяется к a type-id, результат относится к std​::​type_­info объекту, представляющему тип type-id. Если тип type-idявляется ссылкой на возможно cv-квалифицированный тип, результат typeid выражения относится к std​::​type_­info объекту, представляющему cv-неквалифицированный ссылочный тип. Если тип type-idявляется типом класса или ссылкой на тип класса, класс должен быть полностью определен.

Если тип выражения или type-idявляется типом с квалификацией cv, результат typeid выражения ссылается на std​::​type_­info объект, представляющий тип с квалификацией cv. [Example:

class D { /* ... */ };
D d1;
const D d2;

typeid(d1) == typeid(d2);       // yields true
typeid(D)  == typeid(const D);  // yields true
typeid(D)  == typeid(d2);       // yields true
typeid(D)  == typeid(const D&); // yields true

end example]

Если заголовок <typeinfo> не включен до использования typeid, программа имеет неправильный формат.

[ Note: [class.cdtor] описывает поведение, typeid применяемое к объекту, находящемуся в стадии строительства или разрушения. ]end note

Рекомендуемое имя для такого класса extended_­type_­info.

Если p это выражение типа указателя, а затем *p, (*p), *(p), ((*p)), *((p)), и так далее всех удовлетворяют это требование.

8.2.9 Static cast [expr.static.cast]

Результат выражения static_­cast<T>(v) - это результат преобразования выражения v в тип T. Если это ссылочный тип lvalue или ссылка rvalue на тип функции, результатом будет lvalue; если это ссылка rvalue на тип объекта, результатом будет xvalue; в противном случае результатом будет prvalue. Оператор не должен . T T static_­cast cast away constness

- Значение типа «cv1 B», где B это тип класса, может быть приведен к типу «ссылка на cv2 D», где D класс derived от B, если cv2 одно и то же резюме-квалификации , как, или больше резюме , чем-квалификации, cv1. Если B это виртуальный базовый класс D или базовый класс виртуального базового класса D, или если не существует допустимого стандартного преобразования из «указателя на D» в «указатель на B» ([conv.ptr]), программа имеет неправильный формат. Значение xvalue типа «cv1 B» может быть приведено к типу «ссылка rvalue на cv2 D» с теми же ограничениями, что и для lvalue типа «cv1 B». Если объект типа «cv1 B» на самом деле является подобъектом базового класса объекта типа D, результат относится к включающему объекту типа D. В противном случае поведение не определено. [Example:

struct B { };
struct D : public B { };
D d;
B &br = d;

static_cast<D&>(br);            // produces lvalue to the original d object

end example]

Lvalue типа «cv1 T1» может быть приведено к типу «ссылка rvalue на cv2 T2», если «cv2 T2» находится reference-compatible с «cv1 T1». Если значение не является битовым полем, результат относится к объекту или его подобъекту указанного базового класса; в противном случае, lvalue-to-rvalue conversion применяется к битовому полю, а результирующее значение prvalue используется как expressionзначение static_­cast для оставшейся части этого раздела. Если T2 - inaccessible или ambiguous базовый класс T1, программа, которая требует такого приведения, плохо сформирована.

Выражение e может быть явно преобразовано в тип, T если существует implicit conversion sequence от e до Tили если разрешение перегрузки для direct-initialization объекта или ссылки типа T from e найдет хотя бы одну жизнеспособную функцию ([over.match.viable]). Если T это ссылочный тип, эффект такой же, как при объявлении и инициализации.

 T t(e);

для какой-то придуманной временной переменной t ([dcl.init]), а затем использовать временную переменную как результат преобразования. В противном случае объект результата инициализируется напрямую из e. [ Note: Преобразование неправильно сформировано при попытке преобразовать выражение типа класса в недоступный или неоднозначный базовый класс. ]end note

В противном случае static_­cast будет выполнено одно из преобразований, перечисленных ниже. Никакое другое преобразование не должно выполняться явно с использованием файла static_­cast.

Любое выражение может быть явно преобразовано в тип cv void, и в этом случае оно становится discarded-value expression. [ Note: Однако, если значение находится в a temporary object, деструктор для этого объекта не выполняется до обычного времени, а значение объекта сохраняется для выполнения деструктора. ]end note

Обратный любой , standard conversion sequence не содержащий lvalue-to-rvalue, array-to-pointer, function-to-pointer, null pointer, null member pointer, boolean, или function pointer преобразования, может быть выполнены с использованием явно static_­cast. Программа плохо сформирована, если она используется static_­cast для выполнения обратной неверной стандартной последовательности преобразования. [Example:

struct B { };
struct D : private B { };
void f() {
  static_cast<D*>((B*)0);               // error: B is a private base of D
  static_cast<int B::*>((int D::*)0);   // error: B is a private base of D
}

end example]

lvalue-to-rvalue, array-to-pointerИ function-to-pointer преобразования применяются в операнд. На такой static_­cast объект действует ограничение, которое не предусмотрено явным преобразованием cast away constness, а также следующие дополнительные правила для конкретных случаев:

Значение a scoped enumeration type можно явно преобразовать в целочисленный тип. Когда этот тип равен cv bool, результирующее значение будет, false если исходное значение равно нулю и true для всех остальных значений. Для остальных целочисленных типов значение не изменяется, если исходное значение может быть представлено указанным типом. В противном случае результирующее значение не указано. Значение типа перечисления с заданной областью также может быть явно преобразовано в тип с плавающей запятой; результат такой же, как и при преобразовании исходного значения в тип с плавающей запятой.

Значение целочисленного или перечислимого типа может быть явно преобразовано в полный перечисляемый тип. Значение не изменяется, если исходное значение находится в диапазоне значений перечисления ([dcl.enum]). В противном случае поведение не определено. Значение типа с плавающей запятой также можно явно преобразовать в тип перечисления. Результирующее значение совпадает с преобразованием исходного значения в базовый тип enumeration ([conv.fpint]), а затем в тип перечисления.

Prvalue типа «указатель на cv1 B», где B является типом класса, может быть преобразовано в prvalue типа «указатель на cv2 D», где D - это класс derived из B, если cv2 это такая же квалификация cv или более высокая квалификация, чем, cv1. Если B это виртуальный базовый класс D или базовый класс виртуального базового класса D, или если не существует допустимого стандартного преобразования из «указателя на D» в «указатель на B» ([conv.ptr]), программа имеет неправильный формат. null pointer value Преобразуется в значение указателя нулевого типа назначения. Если prvalue типа «указатель на cv1 B» указывает на, B который на самом деле является подобъектом объекта типа D, результирующий указатель указывает на включающий объект типа D. В противном случае поведение не определено.

Prvalue типа «указатель на член D типа cv1 T» может быть преобразован в prvalue типа «указатель на член B типа cv2 T», где B равно a base class of D, если cv2 это такая же квалификация cv или более высокая квалификация cv, чем, cv1.72 Если не существует допустимого стандартного преобразования из «указателя на член B типа T» в «указатель на член D типа T» ([conv.mem]), программа сформирована неправильно. null member pointer value Преобразуются в значение указателя члена нуля типа назначения. Если класс B содержит исходный член или является базовым или производным классом класса, содержащего исходный член, результирующий указатель на член указывает на исходный член. В противном случае поведение не определено. [ Note: Хотя класс B не обязательно должен содержать исходный член, динамический тип объекта, с которым выполняется косвенное обращение через указатель на член, должен содержать исходный член; см [expr.mptr.oper]. ]end note

Prvalue типа «указатель cv1 void» может быть преобразовано в prvalue типа «указатель на cv2 T», где T это тип объекта , и cv2 это тот же CV-квалификацию или более CV-квалификацию , чем, cv1. Если исходное значение указателя представляет собой адрес A байта в памяти и A не удовлетворяет требованию выравнивания T, то результирующее значение указателя не указано. В противном случае, если значение исходных точки указателя на объект a, и есть объект b типа T (без учета CV-квалификация) , который pointer-interconvertible с a, результатом является указателем b. В противном случае значение указателя не изменится при преобразовании. [Example:

T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
bool b = p1 == p2;  // b will have the value true.

end example]

Типы функций (включая те, которые используются в указателях на типы функций-членов) никогда не квалифицируются cv; см [dcl.fct].

8.2.10 Reinterpret cast [expr.reinterpret.cast]

Результат выражения reinterpret_­cast<T>(v) - это результат преобразования выражения v в тип T. Если это ссылочный тип lvalue или ссылка rvalue на тип функции, результатом будет lvalue; если это ссылка rvalue на тип объекта, результатом будет xvalue; в противном случае результатом является prvalue , и для выражения выполняются стандартные преобразования . Преобразования, которые можно выполнить явно с помощью , перечислены ниже. Никакое другое преобразование не может быть выполнено явно с помощью . T T lvalue-to-rvalue array-to-pointer function-to-pointer v reinterpret_­cast reinterpret_­cast

reinterpret_­cast Оператор не должен cast away constness. Выражение целочисленного типа, типа перечисления, указателя или типа указатель на член может быть явно преобразовано в его собственный тип; такое приведение дает значение своего операнда.

[ Note: Отображение, выполненное с помощью, reinterpret_­cast может, а может и не дать представление, отличное от исходного значения. ]end note

Указатель может быть явно преобразован в любой целочисленный тип, достаточно большой, чтобы вместить его. Функция сопоставления определяется реализацией. [ Note: Предполагается, что это неудивительно для тех, кто знает структуру адресации базовой машины. ] Значение типа может быть преобразовано в целочисленный тип; преобразование имеет то же значение и действительность, что и преобразование в целочисленный тип. [ A нельзя использовать для преобразования значения любого типа в тип . ]end note std​::​nullptr_­t (void*)0 Note: reinterpret_­caststd​::​nullptr_­t end note

Значение целочисленного типа или типа перечисления может быть явно преобразовано в указатель. Указатель, преобразованный в целое число достаточного размера (если такое существует в реализации) и обратно в тот же тип указателя, будет иметь свое исходное значение; сопоставления между указателями и целыми числами в противном случае определяются реализацией. [ Note: За исключением случаев, описанных в [basic.stc.dynamic.safety], результатом такого преобразования не будет безопасно полученное значение указателя. ] end note

Указатель на функцию можно явно преобразовать в указатель на функцию другого типа. [ Note: Эффект от вызова функции через указатель на тип функции ([dcl.fct]), который не совпадает с типом, используемым в определении функции, не определен. ] За исключением того, что преобразование prvalue типа «указатель на » в тип «указатель на » (где и являются типами функций) и обратно к исходному типу дает исходное значение указателя, результат такого преобразования указателя не указан. [ См. Также более подробную информацию о преобразованиях указателей. ]end note T1T2 T1 T2 Note: [conv.ptr] end note

Указатель объекта может быть явно преобразован в указатель объекта другого типа.73 Когда prvalue v типа указателя объекта преобразуется в тип указателя объекта «указатель на cv T», результатом является static_­cast<cv T*>(static_­cast<cv void*>(v)). [ Note: Преобразование prvalue типа «указатель на T1» в тип «указатель на T2» (где T1 и T2 являются типами объектов и где требования к выравниванию T2 не строже, чем у T1) и обратно в исходный тип дает исходное значение указателя. ]end note

Преобразование указателя функции в тип указателя объекта или наоборот поддерживается условно. Значение такого преобразования определяется реализацией, за исключением того, что если реализация поддерживает преобразования в обоих направлениях, преобразование prvalue одного типа в другой тип и обратно, возможно, с другой квалификацией cv, должно дать исходное значение указателя.

null pointer value Преобразуется в значение указателя нулевого типа назначения. [ Note: Константа нулевого указателя типа std​::​nullptr_­t не может быть преобразована в тип указателя, а константа нулевого указателя целочисленного типа не обязательно преобразуется в значение нулевого указателя. ]end note

Prvalue типа «указатель на член X типа T1» может быть явно преобразован в prvalue другого типа «указатель на член Y типа T2», если T1 и T2 являются типами функций, или обоими типами объектов. Преобразуются в значение указателя члена нуля типа назначения. Результат этого преобразования не указан, за исключением следующих случаев:74 null member pointer value

  • преобразование prvalue типа «указатель на функцию-член» в другой указатель на тип функции-члена и обратно в исходный тип дает исходный указатель на значение элемента.

  • преобразование prvalue типа «указатель на элемент данных X типа T1» в тип «указатель на элемент данных Y типа T2» (где требования к выравниванию T2 не строже, чем у T1) и обратно к исходному типу дает исходный указатель на значение члена.

Выражение типа glvalue типа T1 может быть приведено к типу «ссылка на T2», если выражение типа «указатель на T1» может быть явно преобразовано в тип «указатель на T2» с помощью reinterpret_­cast. Результат относится к тому же объекту, что и исходное значение glvalue, но с указанным типом. [ Note: То есть, для lvalues, ссылка литой reinterpret_­cast<T&>(x) имеет тот же эффект, что и преобразование *reinterpret_­cast<T*>(&x) с помощью встроенного & и * операторы (и аналогично для reinterpret_­cast<T&&>(x)). ] Нет временно создаются, копия не сделана, и или не называется. end noteconstructors conversion functions 75

Типы могут иметь разные cv-qualifiers, с учетом общего ограничения, что a reinterpret_­cast не может отбросить константность.

T1 и T2 может иметь разные cv-qualifiers, с учетом общего ограничения, что a reinterpret_­cast не может отбросить константность.

Иногда его называют файлом type pun.

8.2.11 Const cast [expr.const.cast]

Результат выражения const_­cast<T>(v) имеет тип T. Если T это lvalue ссылка на тип объекта, результатом будет lvalue; если T это ссылка rvalue на тип объекта, результатом будет xvalue; в противном случае результатом является prvalue lvalue-to-rvalue, array-to-pointerи function-to-pointer для выражения выполняются стандартные преобразования v. Преобразования, которые можно выполнить явно с помощью const_­cast , перечислены ниже. Никакое другое преобразование не должно выполняться явно с использованием const_­cast.

Note: соответствии с ограничениями в этом разделе выражение может быть приведено к собственному типу с помощью const_­cast оператора. ]end note

Для двух similar types T1 и T2prvalue типа T1 может быть явно преобразовано в тип T2 с помощью const_­cast. Результат const_­cast ссылается на исходную сущность. [Example:

typedef int *A[3];               // array of 3 pointer to int
typedef const int *const CA[3];  // array of 3 const pointer to const int

CA &&r = A{}; // OK, reference binds to temporary array object after qualification conversion to type CA
A &&r1 = const_cast<A>(CA{});    // error: temporary array decayed to pointer
A &&r2 = const_cast<A&&>(CA{});  // OK

end example]

Для двух типов объектов T1 и T2, если указатель на T1 может быть явно преобразован в тип «указатель на T2» с помощью a const_­cast, то также могут быть выполнены следующие преобразования:

  • lvalue типа T1 может быть явно преобразовано в lvalue типа T2 с помощью приведения const_­cast<T2&>;

  • glvalue типа T1 может быть явно преобразован в xvalue типа T2 с помощью приведения const_­cast<T2&&>; а также

  • если T1 это тип класса, prvalue типа T1 можно явно преобразовать в xvalue типа T2 с помощью приведения const_­cast<T2&&>.

Результат ссылки const_­cast относится к исходному объекту, если операнд является значением glvalue, и к результату применения в temporary materialization conversion противном случае.

A null pointer value преобразуется в значение нулевого указателя целевого типа. null member pointer value Преобразуются в значение указателя члена нуля типа назначения.

[ Note: В зависимости от типа объекта операция записи через указатель, lvalue или указатель на член данных в результате, const_­cast который отбрасывает константный квалификатор,76 может привести к неопределенному поведению ([dcl.type.cv]). ]end note

Преобразование из типа T1 к типу , T2 casts away constness если T1 и T2 различны, есть cv-decomposition из T1 получая n таким образом, что T2 имеет CV-разложение вида cv20 P20 cv21 P21 cv2n1 P2n1 cv2n U2, и нет квалификации преобразования , который преобразует T1 с cv20 P10 cv21 P11 cv2n1 P1n1 cv2n U1.

Преобразование lvalue типа T1 в lvalue типа T2 с использованием ссылочного преобразования lvalue или преобразование из выражения типа T1 в xvalue типа T2 с использованием ссылочного преобразования rvalue отбрасывает константность, если преобразование из prvalue типа «указатель на T1» на тип «указатель на T2» отбрасывает константность.

[ Note: Некоторые преобразования, которые включают только изменения в cv-квалификации, не могут быть выполнены с использованием. const_­cast. Например, преобразования между указателями на функции не рассматриваются, потому что такие преобразования приводят к значениям, использование которых вызывает неопределенное поведение. По тем же причинам преобразования между указателями на функции-члены и, в частности, преобразование указателя на константную функцию-член в указатель на неконстантную функцию-член не рассматриваются. ]end note

const_­cast не ограничивается преобразованиями, которые отбрасывают квалификатор const.