Стандартные преобразования - это неявные преобразования со встроенным значением. Пункт [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
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.
По историческим причинам это преобразование называется преобразованием «lvalue-to-rvalue», хотя это имя не точно отражает таксономию выражений, описанных в [basic.lval].
В C ++ класс и массив prvalue могут иметь типы с квалификацией cv. Это отличается от ISO C, в котором значения, отличные от lvalue, никогда не имеют типов с квалификацией cv.
Lvalue или rvalue типа «массив N T» или «массив с неизвестной границей T» может быть преобразован в prvalue типа «указатель на T». temporary materialization conversion Применяется. Результат - указатель на первый элемент массива.
Lvalue типа функции T может быть преобразовано в prvalue типа «указатель на T». Результат - указатель на функцию.59
[ Note: См. [over.over] Дополнительные правила для случая, когда функция перегружена. ] — end note
Это преобразование никогда не применяется к нестатическим функциям-членам, поскольку не может быть получено значение lvalue, которое относится к нестатической функции-члену.
Prvalue типа T можно преобразовать в xvalue типа T. Это преобразование инициализирует temporary object тип T из prvalue, оценивая prvalue с временным объектом в качестве объекта результата, и производит xvalue, обозначающее временный объект. T должен быть законченным типом. [ Note: Если T это тип класса (или его массив), он должен иметь доступный и не удаленный деструктор; см [class.dtor]. ] [ — end note Example:
struct X { int n; };
int k = X().n; // OK, X() prvalue is converted to xvalue
— end example ]
cv-decomposition Типа T представляет собой последовательность ,cvi и Pi таким образом, что T является «cv0 P0 cv1 P1 ⋯ cvn−1 Pn−1 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
Эти правила гарантируют, что константная безопасность сохраняется при преобразовании.
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 целочисленного типа может быть преобразовано в prvalue другого целочисленного типа. Prvalue типа перечисления с незаданной областью может быть преобразовано в prvalue целочисленного типа.
Если целевой тип беззнаковый, результирующее значение является наименьшим беззнаковым целым числом, совпадающим с исходным целым числом (по модулю, 2n где n - количество битов, используемых для представления беззнакового типа). [ Note: В представлении с дополнением до двух это преобразование является концептуальным, и битовый шаблон не изменяется (если нет усечения). ] — end note
Если тип назначения подписан, значение не изменяется, если оно может быть представлено в типе назначения; в противном случае значение определяется реализацией.
Если тип назначения - boolсм [conv.bool]. Если исходный тип равен bool, значение false преобразуется в ноль, а значение true преобразуется в единицу.
Prvalue типа с плавающей запятой можно преобразовать в prvalue другого типа с плавающей запятой. Если исходное значение может быть точно представлено в целевом типе, результатом преобразования будет это точное представление. Если исходное значение находится между двумя соседними целевыми значениями, результатом преобразования является выбор любого из этих значений, определяемый реализацией. В противном случае поведение не определено.
Prvalue типа с плавающей запятой можно преобразовать в prvalue целочисленного типа. Преобразование обрезается; то есть дробная часть отбрасывается. Поведение не определено, если усеченное значение не может быть представлено в целевом типе. [ Note: Если тип назначения - boolсм [conv.bool]. ] — end note
Prvalue целочисленного типа или типа перечисления с незаданной областью может быть преобразовано в prvalue типа с плавающей запятой. Результат по возможности точный. Если преобразуемое значение находится в диапазоне значений, которые могут быть представлены, но значение не может быть представлено точно, это определяется реализацией выбора следующего более низкого или более высокого представляемого значения. [ Note: Потеря точности происходит, если целое значение не может быть представлено точно как значение плавающего типа. ] Если преобразуемое значение выходит за пределы диапазона значений, которые могут быть представлены, поведение не определено. Если исходный тип равен , значение преобразуется в ноль, а значение преобразуется в единицу. — end note bool false true
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, программа, которая требует этого преобразования, плохо сформирована. Результатом преобразования является указатель на подобъект базового класса объекта производного класса. Значение нулевого указателя преобразуется в значение нулевого указателя целевого типа.
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*.
Значение типа «указатель на 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 ]
Значение арифметики, перечисление без области действия, указатель или указатель на тип элемента может быть преобразовано в значение типа bool. Нулевое значение, значение нулевого указателя или значение указателя нулевого члена преобразуются в false; любое другое значение преобразуется в true. Для direct-initializationprvalue типа std::nullptr_t можно преобразовать в prvalue типа bool; итоговое значение равно false.
Каждый целочисленный тип имеет следующее 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