Этот подпункт содержит шаблоны, которые могут использоваться для преобразования одного типа в другой в соответствии с некоторым предопределенным правилом.
Шаблон | Комментарии |
template <class T> struct remove_reference; | ЕслиT имеет тип «ссылка наT1», тогдаtype имена typedef членаT1; в противном случае -type именаT. |
template <class T> struct add_lvalue_reference; | ЕслиT имена a,referenceable type то член typedeftype namesT&; в противном случае -type именаT. [ Note: Это правило отражает семантику свертывания ссылок ([dcl.ref]). ] — end note |
template <class T> struct add_rvalue_reference; | ЕслиT именует Referenceable типа , то члены ЬурейеГоtype именT&&; в противном случае -type именаT. [ Note: Это правило отражает семантику свертывания ссылок ([dcl.ref]). Например, когда типT называет типT1&, этот тип add_rvalue_reference_t<T> не является ссылкой rvalue. ] — end note |
Шаблон | Комментарии |
template <class T> struct make_signed; |
ЕслиT именует a (возможно, cv-квалифицированным),
signed integer type тогда typedef члена
type называет типT; в противном случае, еслиT именуется (возможно, cv-квалифицированный) беззнаковый целочисленный тип, тогдаtype именуется соответствующий знаковый целочисленный тип с теми же cv-квалификаторами, что иT; в противном случае,type именует знаковое целое типа с ,smallest
rank для которых
sizeof(T) == sizeof(type), с тем же CV-определителями какT. Requires:T должен быть (возможно, cv-квалифицированным) целочисленным типом или перечислением, но неbool типом. |
template <class T> struct make_unsigned; |
ЕслиT именует a (возможно, cv-квалифицированным),
unsigned integer type тогда typedef члена
type называет типT; в противном случае, еслиT именуется (возможно, cv-квалифицированный) целочисленный тип со знаком, тогдаtype именуется соответствующий беззнаковый целочисленный тип с теми же cv-квалификаторами, что иT; в противном случае,type называют целое число без знака типа с ,smallest
rank для которого
sizeof(T) == sizeof(type), с тем же CV-классификаторами какT. Requires:T должен быть (возможно, cv-квалифицированным) целочисленным типом или перечислением, но неbool типом. |
[ Example:
// the following assertions hold:
assert((is_same_v<remove_extent_t<int>, int>));
assert((is_same_v<remove_extent_t<int[2]>, int>));
assert((is_same_v<remove_extent_t<int[2][3]>, int[3]>));
assert((is_same_v<remove_extent_t<int[][3]>, int[3]>));
— end example ]
Шаблон | Комментарии |
template <class T> struct remove_pointer; | ЕслиT имеет тип «(возможно , резюме квалифицированное) указательT1» затем член ЬурейеГоtype именT1; в противном случае это именаT. |
template <class T> struct add_pointer; | ЕслиT называет типreferenceable type или cvvoid тип, то член typedeftype называет тот же тип, что и remove_reference_t<T>*; в противном случае -type именаT. |
Шаблон | Комментарии |
template <size_t Len, size_t Align = default-alignment> struct aligned_storage; |
Значениеdefault-alignment должно быть наиболее строгим требованием к выравниванию для любого типа объекта C ++, размер которого не превышаетLen ([basic.types]). Член typedeftype должен быть типом POD, подходящим для использования в качестве неинициализированного хранилища для любого объекта, размер которого не больше,Len а выравнивание является делителемAlign. Requires:Len не должно быть нулевым.Align должен быть равен alignof(T) для некоторого типаT или todefault-alignment. |
template <size_t Len, class... Types> struct aligned_union; |
Элемент typedeftype должен быть типом POD, подходящим для использования в качестве неинициализированного хранилища для любого объекта, тип которого указан вTypes; его размер должен быть не менееLen. Статический членalignment_value
должен быть интегральной константой типаsize_t , значение которого является самым строгим выравниванием из всех типов, перечисленных вTypes. Requires: Предусмотрен хотя бы один тип. |
template <class T> struct decay; | ПустьU будетremove_reference_t<T>. Еслиis_array_v<U> есть true, то член typedeftype должен быть равен remove_extent_t<U>*. Еслиis_function_v<U> естьtrue, то член typedeftype должен быть равенadd_pointer_t<U>. В противном случае typedef членаtype равенremove_cv_t<U>. [ Note: Это поведение похоже наlvalue-to-rvalue, array-to-pointerиfunction-to-pointer преобразование применяется , когда выражение - значения используется в качестве RValue, но и полоскаcv-qualifiers от типов классов , с тем чтобы более точно моделями по значению передачи аргументов. ] — end note |
template <bool B, class T = void>struct enable_if; | ЕслиB естьtrue, то член typedeftype должен быть равенT; в противном случае член не должен быть type. |
template <bool B, class T,
class F> struct conditional; | ЕслиB естьtrue, то член typedeftype должен быть равенT. ЕслиB естьfalse, то член typedeftype должен быть равенF. |
template <class... T>struct common_type; | Если этот признак не является специализированным (как указано в примечании B ниже), членtype должен быть определен или опущен, как указано в примечании A ниже. Если он опущен, член не должен бытьtype. Каждый тип в пакете параметровT должен быть полнымcvvoidили массивом с неизвестными границами. |
template <class T> struct underlying_type; |
Элемент typedeftype называет базовый типT. Requires:T должен быть полнымenumeration type |
template <class Fn, class... ArgTypes> struct invoke_result; |
Если выражениеINVOKE(declval<Fn>(), declval<ArgTypes>()...)
правильно сформировано при обработке как выражениеunevaluated operand, typedef членаtype называет тип
decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)); в противном случае член не должен бытьtype. Проверка доступа выполняется, как если бы в контексте, не связанном сFn и
ArgTypes. Учитывается только действительность непосредственного контекста выражения. [ Note:
Компиляция выражения может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций, создание неявно определенных функций и т. Д. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному формированию программы.
] и все типы в пакете параметров должны быть полными типами или массивами с неизвестной границей. — end note Requires:Fn ArgTypes cvvoid |
[ Note: Типичная реализация определяется aligned_storageкак:
template <size_t Len, size_t Alignment> struct aligned_storage { typedef struct { alignas(Alignment) unsigned char __data[Len]; } type; };
— end note ]
Примечание A: Для common_typeпризнака, применяемого к пакету параметровT типов, членtype должен быть либо определен, либо отсутствовать следующим образом:
Еслиsizeof...(T) равно нулю, не должно быть никакого членаtype.
Еслиsizeof...(T) это один, пустьT0 обозначает единственный тип, составляющий пачкуT. Член typedef-nametype должен обозначать тот же тип, если таковой имеется, что иcommon_type_t<T0, T0>; в противном случае член не будетtype.
Еслиsizeof...(T) равно двум, пусть первый и второй составляющие типыT обозначаются символамиT1 иT2, соответственно, и пустьD1 иD2 обозначают те же типы, чтоdecay_t<T1> и иdecay_t<T2>, соответственно.
Еслиis_same_v<T1, D1> естьfalse или is_same_v<T2, D2> естьfalse, пустьC обозначает тот же тип, если есть, какcommon_type_t<D1, D2>.
В противном случае позвольтеC обозначить тот же тип, если таковой имеется, как
decay_t<decltype(false ? declval<D1>() : declval<D2>())>
[ Note: Это не будет применяться, если есть специализацияcommon_type<D1, D2>. ] — end note
В любом случае член typedef-nametype должен обозначать тот же тип, если таковой имеется, какC. В противном случае член не будетtype.
Еслиsizeof...(T) больше двух, пустьT1,T2иR, соответственно, обозначают первый, второй и (пакет) остальных составляющих типовT. ПозвольтеC обозначить тот же тип, если таковой имеется, какcommon_type_t<T1, T2>. Если есть такой типC, член typedef-nametype должен обозначать тот же тип, если таковой имеется, какcommon_type_t<C, R...>. В противном случае член не будетtype.
Примечание Б. Несмотря на положения[meta.type.synop]и в соответствии с ними[namespace.std], программа может специализироватьсяcommon_type<T1, T2> на типахT1 иT2 таких, которые is_same_v<T1, decay_t<T1>> и is_same_v<T2, decay_t<T2>> являются каждым из нихtrue. [ Note: Такие специализации необходимы, когда требуются только явные преобразования между аргументами шаблона. ] У такой специализации не обязательно должен быть член с именем , но если он есть, этот член должен быть доступным и однозначным cv-unqualified не ссылочным типом, в который каждый из типов и может быть явно преобразован. Кроме того, будет обозначать тот же тип, если таковой имеется . Нарушение правил данной заметки не требует диагностики. — end note typetypedef-nameCT1 T2 common_type_t<T1, T2> common_type_t<T2, T1>
[ Example: Учитывая эти определения:
using PF1 = bool (&)(); using PF2 = short (*)(long); struct S { operator PF2() const; double operator()(char, int&); void fn(long) const; char data; }; using PMF = void (S::*)(long) const; using PMD = char S::*;
справедливы следующие утверждения:
static_assert(is_same_v<invoke_result_t<S, int>, short>); static_assert(is_same_v<invoke_result_t<S&, unsigned char, int&>, double>); static_assert(is_same_v<invoke_result_t<PF1>, bool>); static_assert(is_same_v<invoke_result_t<PMF, unique_ptr<S>, int>, void>); static_assert(is_same_v<invoke_result_t<PMD, S>, char&&>); static_assert(is_same_v<invoke_result_t<PMD, const S*>, const char&>);
— end example ]