8 Expressions [expr]

8.2 Postfix expressions [expr.post]

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].