23 General utilities library [utilities]

23.15 Metaprogramming and type traits [meta]

23.15.7 Transformations between types [meta.trans]

23.15.7.6 Other transformations [meta.trans.other]

Таблица 50 - Прочие преобразования
ШаблонКомментарии
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]

Это определяется реализация любого ли extended alignment поддерживаются.

Примечание 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]