7 Standard conversions [conv]

Стандартные преобразования - это неявные преобразования со встроенным значением. Пункт [conv] перечисляет полный набор таких преобразований. A standard conversion sequence - это последовательность стандартных преобразований в следующем порядке:

  • Ноль или одно преобразование из следующего набора: преобразование lvalue-to-rvalue, преобразование массива в указатель и преобразование функции в указатель.

  • Ноль или одно преобразование из следующего набора: целочисленные продвижения, продвижение с плавающей запятой, интегральные преобразования, преобразования с плавающей запятой, преобразования с плавающей запятой, преобразования указателя, преобразования указателя в член и преобразования логического типа.

  • Преобразование нулевого или одного указателя на функцию.

  • Ноль или одно преобразование квалификации.

[ Note: Стандартная последовательность преобразования может быть пустой, т. Е. Не содержать преобразований. ] Стандартная последовательность преобразования будет применена к выражению, если необходимо преобразовать его в требуемый тип назначения. end note

[ Note: Выражения с заданным типом будут неявно преобразованы в другие типы в нескольких контекстах:

  • При использовании в качестве операндов операторов. Требования оператора к его операндам определяют тип назначения (пункт [expr]).

  • При использовании в условии if оператора или оператора итерации ([stmt.select], [stmt.iter]). Тип назначения - bool.

  • Когда используется в выражении switch утверждения. Тип назначения - интегральный ([stmt.select]).

  • При использовании в качестве исходного выражения для инициализации (что включает использование в качестве аргумента при вызове функции и использование в качестве выражения в return инструкции). Тип инициализируемой сущности (как правило) является типом назначения. См [dcl.init], [dcl.init.ref].

end note]

Выражение e может относиться implicitly converted к типу T тогда и только тогда, когда объявление T t=e; правильно сформировано для некоторой придуманной временной переменной t ([dcl.init]).

Некоторые языковые конструкции требуют преобразования выражения в логическое значение. Выражение, e появляющееся в таком контексте, называется contextually converted to bool правильно сформированным тогда и только тогда, когда объявление bool t(e); правильно сформировано для некоторой придуманной временной переменной t ([dcl.init]).

Для некоторых языковых конструкций требуется преобразование в значение, имеющее один из указанного набора типов, соответствующих конструкции. Выражение e типа класса, E появляющееся в таком контексте, считается относящимся contextually implicitly converted к указанному типу T и является правильно сформированным тогда и только тогда, когда e может быть неявно преобразовано в тип, T который определяется следующим образом: E ищется неявные функции преобразования, возвращающие type - это cv T или ссылка на то cv T , что T разрешено контекстом. Таких должен быть ровно один T.

Эффект от любого неявного преобразования такой же, как при выполнении соответствующего объявления и инициализации с последующим использованием временной переменной в качестве результата преобразования. Результатом является lvalue, если T это ссылочный тип lvalue, или ссылка rvalue на функцию type ([dcl.ref]), xvalue, если T ссылка rvalue на тип объекта, и prvalue в противном случае. Выражение e используется как glvalue тогда и только тогда, когда инициализация использует его как glvalue.

[ Note: Для типов классов также рассматриваются определенные пользователем преобразования; см [class.conv]. Как правило, implicit conversion sequence состоит из стандартной последовательности преобразования, за которой следует определяемое пользователем преобразование, за которым следует другая стандартная последовательность преобразования. ]end note

[ Note: В некоторых случаях определенные преобразования запрещены. Например, преобразование lvalue-to-rvalue не выполняется для операнда унарного & оператора. Конкретные исключения приведены в описаниях этих операторов и контекстов. ]end note

7.1 Lvalue-to-rvalue conversion [conv.lval]

A glvalue нефункционального типа, T не являющегося массивом, может быть преобразован в prvalue.57 Если T это неполный тип, программа, которая требует этого преобразования, плохо сформирована. Если T это неклассовый тип, то тип prvalue - это неквалифицированная версия cv T. В противном случае тип prvalue - T.58

Когда преобразование lvalue-to-rvalue применяется к выражению e, и либо

  • e потенциально не оценивается, или

  • оценка e результатов при оценке члена ex множества потенциальных результатов eи ex именует переменную, x которая не odr-used является ex,

значение, содержащееся в указанном объекте, недоступно. [Example:

struct S { int n; };
auto f() {
  S x { 1 };
  constexpr S y { 2 };
  return [&](bool b) { return (b ? y : x).n; };
}
auto g = f();
int m = g(false);   // undefined behavior due to access of x.n outside its lifetime
int n = g(true);    // OK, does not access y.n

end example]

Результат конвертации определяется по следующим правилам:

  • Если T есть cv std​::​nullptr_­t, то результатом будет null pointer constant. [ Note: Поскольку значение не извлекается из памяти, нет побочного эффекта для энергозависимого доступа ([intro.execution]), и union можно получить доступ к неактивному члену a . ]end note

  • В противном случае, если T есть тип класса, преобразование копирует-инициализирует объект результата из glvalue.

  • В противном случае, если объект, на который ссылается glvalue, содержит недопустимое значение указателя ([basic.stc.dynamic.deallocation], [basic.stc.dynamic.safety]), поведение определяется реализацией.

  • В противном случае значение, содержащееся в объекте, указанном параметром glvalue, является результатом prvalue.

[ Note: См. Также [basic.lval]. ]end note

По историческим причинам это преобразование называется преобразованием «lvalue-to-rvalue», хотя это имя не точно отражает таксономию выражений, описанных в [basic.lval].

В C ++ класс и массив prvalue могут иметь типы с квалификацией cv. Это отличается от ISO C, в котором значения, отличные от lvalue, никогда не имеют типов с квалификацией cv.

7.2 Array-to-pointer conversion [conv.array]

Lvalue или rvalue типа «массив N T» или «массив с неизвестной границей T» может быть преобразован в prvalue типа «указатель на T». temporary materialization conversion Применяется. Результат - указатель на первый элемент массива.

7.3 Function-to-pointer conversion [conv.func]

Lvalue типа функции T может быть преобразовано в prvalue типа «указатель на T». Результат - указатель на функцию.59

[ Note: См. [over.over] Дополнительные правила для случая, когда функция перегружена. ]end note

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

7.4 Temporary materialization conversion [conv.rval]

Prvalue типа T можно преобразовать в xvalue типа T. Это преобразование инициализирует temporary object тип T из prvalue, оценивая prvalue с временным объектом в качестве объекта результата, и производит xvalue, обозначающее временный объект. T должен быть законченным типом. [ Note: Если T это тип класса (или его массив), он должен иметь доступный и не удаленный деструктор; см [class.dtor]. ] [end noteExample:

struct X { int n; };
int k = X().n;      // OK, X() prvalue is converted to xvalue

end example]

7.5 Qualification conversions [conv.qual]

cv-decomposition Типа T представляет собой последовательность ,cvi и Pi таким образом, что T является «cv0 P0 cv1 P1 cvn1 Pn1 cvn U» для n>0, где каждый cvi представляет собой набор cv-qualifiers, и каждый Pi представляет “pointer to”, “pointer to member of class Ci of type”«массив Ni», или «array of unknown bound из». Если Pi обозначает массив, cv-квалификаторы cvi+1 для типа элемента также принимаются как cv-квалификаторы cvi массива. [ Example: Тип, обозначенный символом, type-id const int ** имеет два cv-разложения U : «int» и «указатель на const int». ] Набор cv-квалификаторов после первого в самом длинном cv-разложении , то есть, называется of .end example n Tcv1,cv2,,cvncv-qualification signature T

Два типа T1 и T2 есть, similar если они имеют cv-разложения с одинаковыми n , так что соответствующие Pi компоненты одинаковы и типы, обозначенные U одинаковыми.

Выражение prvalue типа T1 может быть преобразовано в тип, T2 если выполняются следующие условия, где cvji обозначает cv-квалификаторы в сигнатуре cv-qualification Tj:60

  • T1 и T2 похожи.

  • Для каждого i>0, если const находится в, cv1i то const есть в cv2i, и аналогично для volatile.

  • Если символы cv1i и cv2i разные, то const находится в каждом cv2k for 0<k<i.

[ Note: Если программа могла назначить указатель типа T** указателю типа const T** (то есть, если была разрешена строка № 1 ниже), программа могла непреднамеренно изменить const объект (как это делается в строке № 2). Например,

int main() {
  const char c = 'c';
  char* pc;
  const char** pcc = &pc;       // #1: not allowed
  *pcc = &c;
  *pc = 'C';                    // #2: modifies a const object
}

end note]

[ Note: Prvalue типа «указатель на cv1 T» может быть преобразовано в prvalue типа «указатель на cv2 T», если «cv2 T» более квалифицировано cv, чем «cv1 T». Prvalue типа «указатель на член X типа cv1 T» может быть преобразовано в prvalue типа «указатель на член X типа cv2 T», если «cv2 T» более квалифицировано cv, чем «cv1 T». ]end note

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

Эти правила гарантируют, что константная безопасность сохраняется при преобразовании.

7.6 Integral promotions [conv.prom]

Prvalue целого числа типа, кроме bool, char16_­t, char32_­t, или wchar_­t чей integer conversion rank меньше , чем ранг int может быть преобразованы в prvalue типа , int если int можно представить все значения типа источника; в противном случае исходное prvalue может быть преобразовано в prvalue типа unsigned int.

Prvalue типа char16_­t, char32_­tили wchar_­t ([basic.fundamental]) может быть преобразовано в prvalue первого из следующих типов , которые могут представлять все значения его базового типа: int, unsigned int, long int, unsigned long int, long long int, или unsigned long long int. Если ни один из типов в этом списке не может представлять все значения его базового типа, а prvalue типа char16_­t, char32_­tили wchar_­t может быть преобразовано в prvalue его базового типа.

Prvalue типа перечисления с незаданной областью, базовый тип которого не fixed ([dcl.enum]), может быть преобразован в prvalue первого из следующих типов, который может представлять все значения перечисления (т. Е. Значения в диапазоне bmin до, bmax как описано в [dcl.enum]) : int, unsigned int, long int, unsigned long int, long long int, или unsigned long long int. Если ни один из типов в этом списке не может представлять все значения перечисления, prvalue типа перечисления с незаданной областью может быть преобразовано в prvalue расширенного целочисленного типа с наименьшим integer conversion rank выше, чем ранг, long long в котором все значения перечисления могут быть представлены. Если таких расширенных типов два, выбирается подписанный.

Prvalue типа перечисления с незаданной областью, базовый тип которого fixed ([dcl.enum]), может быть преобразован в prvalue его базового типа. Более того, если интегральное продвижение может быть применено к его базовому типу, prvalue типа перечисления с незаданной областью, базовый тип которого фиксирован, также может быть преобразован в prvalue продвинутого базового типа.

Prvalue для интеграла bit-field может быть преобразовано в prvalue типа, int если int может представлять все значения битового поля; в противном случае он может быть преобразован в unsigned int if, который unsigned int может представлять все значения битового поля. Если битовое поле еще больше, к нему не применяется интегральное продвижение. Если битовое поле имеет перечислимый тип, оно рассматривается как любое другое значение этого типа в целях продвижения.

Prvalue типа bool может быть преобразован в prvalue типа int, false становясь равным нулю и равным true единице.

Эти преобразования называются integral promotions.

7.7 Floating-point promotion [conv.fpprom]

Prvalue типа float можно преобразовать в prvalue типа double. Стоимость не изменилась.

Это преобразование называется floating-point promotion.

7.8 Integral conversions [conv.integral]

Prvalue целочисленного типа может быть преобразовано в prvalue другого целочисленного типа. Prvalue типа перечисления с незаданной областью может быть преобразовано в prvalue целочисленного типа.

Если целевой тип беззнаковый, результирующее значение является наименьшим беззнаковым целым числом, совпадающим с исходным целым числом (по модулю, 2n где n - количество битов, используемых для представления беззнакового типа). [ Note: В представлении с дополнением до двух это преобразование является концептуальным, и битовый шаблон не изменяется (если нет усечения). ]end note

Если тип назначения подписан, значение не изменяется, если оно может быть представлено в типе назначения; в противном случае значение определяется реализацией.

Если тип назначения - boolсм [conv.bool]. Если исходный тип равен bool, значение false преобразуется в ноль, а значение true преобразуется в единицу.

Преобразования, разрешенные как интегральные продвижения, исключаются из набора интегральных преобразований.

7.9 Floating-point conversions [conv.double]

Prvalue типа с плавающей запятой можно преобразовать в prvalue другого типа с плавающей запятой. Если исходное значение может быть точно представлено в целевом типе, результатом преобразования будет это точное представление. Если исходное значение находится между двумя соседними целевыми значениями, результатом преобразования является выбор любого из этих значений, определяемый реализацией. В противном случае поведение не определено.

Преобразования, разрешенные как продвижение с плавающей запятой, исключаются из набора преобразований с плавающей запятой.

7.10 Floating-integral conversions [conv.fpint]

Prvalue типа с плавающей запятой можно преобразовать в prvalue целочисленного типа. Преобразование обрезается; то есть дробная часть отбрасывается. Поведение не определено, если усеченное значение не может быть представлено в целевом типе. [ Note: Если тип назначения - boolсм [conv.bool]. ]end note

Prvalue целочисленного типа или типа перечисления с незаданной областью может быть преобразовано в prvalue типа с плавающей запятой. Результат по возможности точный. Если преобразуемое значение находится в диапазоне значений, которые могут быть представлены, но значение не может быть представлено точно, это определяется реализацией выбора следующего более низкого или более высокого представляемого значения. [ Note: Потеря точности происходит, если целое значение не может быть представлено точно как значение плавающего типа. ] Если преобразуемое значение выходит за пределы диапазона значений, которые могут быть представлены, поведение не определено. Если исходный тип равен , значение преобразуется в ноль, а значение преобразуется в единицу. end note bool false true

7.11 Pointer conversions [conv.ptr]

A null pointer constant - это integer literal нулевое значение или prvalue типа std​::​nullptr_­t. Константа нулевого указателя может быть преобразована в тип указателя; результат относится к null pointer value этому типу и отличается от любого другого значения указателя на объект или типа указателя на функцию. Такое преобразование называется файлом null pointer conversion. Два значения нулевого указателя одного и того же типа должны сравниваться как равные. Преобразование константы нулевого указателя в указатель на тип, квалифицированный cv, является одним преобразованием, а не последовательностью преобразования указателя, за которым следует qualification conversion. Константа нулевого указателя целочисленного типа может быть преобразована в значение типа pr std​::​nullptr_­t. [ Note: Результирующее значение prvalue не является значением нулевого указателя. ] end note

Prvalue типа «указатель на cv T», где T является типом объекта, может быть преобразовано в prvalue типа «указатель на cv void». При pointer value этом преобразовании не изменяется.

Prvalue типа «указатель на cv D», где D является типом класса, может быть преобразовано в prvalue типа «указатель на cv B», где B - base class из D. Если B - inaccessible или ambiguous базовый класс D, программа, которая требует этого преобразования, плохо сформирована. Результатом преобразования является указатель на подобъект базового класса объекта производного класса. Значение нулевого указателя преобразуется в значение нулевого указателя целевого типа.

7.12 Pointer to member conversions [conv.mem]

A null pointer constant можно преобразовать в указатель на тип члена; результат является null member pointer value элементом этого типа, и его можно отличить от любого указателя на член, не созданного из константы нулевого указателя. Такое преобразование называется файлом null member pointer conversion. Два значения указателя нулевого члена одного и того же типа должны сравниваться как равные. Преобразование константы нулевого указателя в указатель на член типа с квалификацией cv является одним преобразованием, а не последовательностью преобразования указателя в член, за которым следует qualification conversion.

Prvalue типа «указатель на член B типа cv T», где B является типом класса, может быть преобразовано в prvalue типа «указатель на член D типа cv T», где D - derived class из B. Если B это inaccessible, ambiguousили virtual базовый класс D, или базовый класс виртуального базового класса D, программа , которая делает необходимую это преобразование плохо сформировано. Результат преобразования относится к тому же члену, что и указатель на член до того, как произошло преобразование, но он относится к члену базового класса, как если бы он был членом производного класса. Результат относится к члену в Dэкземпляре B. Поскольку результат имеет тип «указатель на член D типа cv T», косвенное обращение к нему с D объектом допустимо. Результат такой же, как при косвенном указателе на член B с B подобъектом D. Значение указателя нулевого члена преобразуется в значение указателя нулевого члена целевого типа.61

Правило преобразования указателей в члены (из указателя на член базы в указатель на член производного) кажется инвертированным по сравнению с правилом для указателей на объекты (из указателя в производный в указатель на базу) ([conv.ptr], Предложение [class.derived]). Эта инверсия необходима для обеспечения безопасности типа. Обратите внимание, что указатель на член не является указателем объекта или указателем функции, и правила преобразования таких указателей не применяются к указателям на члены. В частности, указатель на член не может быть преобразован в void*.

7.13 Function pointer conversions [conv.fctptr]

Значение типа «указатель на noexcept функцию» может быть преобразовано в значение типа «указатель на функцию». Результат - указатель на функцию. Prvalue типа «указатель на член noexcept функции типа » может быть преобразовано в prvalue типа «указатель на член функции типа». Результат указывает на функцию-член.

[Example:

  void (*p)();
  void (**pp)() noexcept = &p;  // error: cannot convert to pointer to noexcept function

  struct S { typedef void (*p)(); operator p(); };
  void (*q)() noexcept = S();   // error: cannot convert to pointer to noexcept function

end example]

7.14 Boolean conversions [conv.bool]

Значение арифметики, перечисление без области действия, указатель или указатель на тип элемента может быть преобразовано в значение типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого члена преобразуются в false; любое другое значение преобразуется в true. Для direct-initializationprvalue типа std​::​nullptr_­t можно преобразовать в prvalue типа bool; итоговое значение равно false.

7.15 Integer conversion rank [conv.rank]

Каждый целочисленный тип имеет следующее integer conversion rank определение:

  • Никакие два знаковых целочисленных типа, кроме char и signed char (если char знаковый), не должны иметь одинаковый ранг, даже если они имеют одинаковое представление.

  • Ранг целочисленного типа со знаком должен быть выше ранга любого целочисленного типа со знаком меньшего размера.

  • Ранг long long int должен быть выше ранга long int, который должен быть выше ранга int, который должен быть выше ранга short int, который должен быть выше ранга signed char.

  • Ранг любого целочисленного типа без знака должен равняться рангу соответствующего целочисленного типа со знаком.

  • Ранг любого стандартного целочисленного типа должен быть выше ранга любого расширенного целочисленного типа того же размера.

  • Ранг char равен рангу signed char и unsigned char.

  • Ранг bool должен быть меньше ранга всех других стандартных целочисленных типов.

  • Ряды char16_­t, char32_­tи wchar_­t равняются ряды их underlying types.

  • Ранг любого расширенного целочисленного типа со знаком относительно другого расширенного целочисленного типа со знаком того же размера определяется реализацией, но по-прежнему подчиняется другим правилам определения ранга преобразования целого числа.

  • Для всех целочисленных типов T1, T2и T3, если T1 имеет больший ранг T2 и T2 имеет больший ранг T3, то T1 должен иметь больший ранг, чем T3.

[ Note: Ранг целочисленного преобразования используется в определении integral promotions и usual arithmetic conversions. ] end note