Шаблон | Комментарии |
template <size_t Len, size_t Align = default-alignment> struct aligned_storage; |
Значение default-alignment должно быть наиболее строгим требованием к выравниванию для любого типа объекта C ++, размер которого не превышает Len ([basic.types]). Член typedef type должен быть типом POD, подходящим для использования в качестве неинициализированного хранилища для любого объекта, размер которого не больше, Len а выравнивание является делителем Align. Requires: Len не должно быть нулевым. Align должен быть равен alignof(T) для некоторого типа T или to default-alignment. |
template <size_t Len, class... Types> struct aligned_union; |
Элемент typedef type должен быть типом POD, подходящим для использования в качестве неинициализированного хранилища для любого объекта, тип которого указан в Types; его размер должен быть не менее Len. Статический член alignment_value
должен быть интегральной константой типа size_t , значение которого является самым строгим выравниванием из всех типов, перечисленных в Types. Requires: Предусмотрен хотя бы один тип. |
template <class T> struct decay; | Пусть U будет remove_reference_t<T>. Если is_array_v<U> есть true, то член typedef type должен быть равен remove_extent_t<U>*. Если is_function_v<U> есть true, то член typedef type должен быть равен 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, то член typedef type должен быть равен T; в противном случае член не должен быть type. |
template <bool B, class T,
class F> struct conditional; | Если B есть true, то член typedef type должен быть равен T. Если B есть false, то член typedef type должен быть равен F. |
template <class... T> struct common_type; | Если этот признак не является специализированным (как указано в примечании B ниже), член type должен быть определен или опущен, как указано в примечании A ниже. Если он опущен, член не должен быть type. Каждый тип в пакете параметров T должен быть полным cv voidили массивом с неизвестными границами. |
template <class T> struct underlying_type; |
Элемент typedef type называет базовый тип 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 cv void |
[ 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-name type должен обозначать тот же тип, если таковой имеется, что и 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-name type должен обозначать тот же тип, если таковой имеется, как C. В противном случае член не будет type.
Если sizeof...(T) больше двух, пусть T1, T2и R, соответственно, обозначают первый, второй и (пакет) остальных составляющих типов T. Позвольте C обозначить тот же тип, если таковой имеется, как common_type_t<T1, T2>. Если есть такой тип C, член typedef-name type должен обозначать тот же тип, если таковой имеется, как 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-name C T1 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 ]