23 General utilities library [utilities]

23.8 Storage for any type [any]

В этом разделе описаны компоненты, которые программы C ++ могут использовать для выполнения операций с объектами размеченного типа.

[ Note: Размеченный тип может содержать значения разных типов, но не пытается5 выполнить преобразование между ними, т.е. хранится строго какint и не может быть неявно преобразован ни в,"5" ни в5.0. Это безразличие к интерпретации, но осведомленность о типе позволяет эффективно использовать безопасные универсальные контейнеры с отдельными значениями без каких-либо сюрпризов от неоднозначных преобразований. ]end note

23.8.1 Header <any> synopsis [any.synop]

namespace std {
  // [any.bad_any_cast], class bad_­any_­cast
  class bad_any_cast;

  // [any.class], class any
  class any;

  // [any.nonmembers], non-member functions
  void swap(any& x, any& y) noexcept;

  template <class T, class... Args>
    any make_any(Args&& ...args);
  template <class T, class U, class... Args>
    any make_any(initializer_list<U> il, Args&& ...args);

  template<class T>
    T any_cast(const any& operand);
  template<class T>
    T any_cast(any& operand);
  template<class T>
    T any_cast(any&& operand);

  template<class T>
    const T* any_cast(const any* operand) noexcept;
  template<class T>
    T* any_cast(any* operand) noexcept;
}

23.8.2 Class bad_­any_­cast [any.bad_any_cast]

class bad_any_cast : public bad_cast {
public:
  const char* what() const noexcept override;
};

Объекты типаbad_­any_­cast брошены неудачником any_­cast.

const char* what() const noexcept override;

Returns: An реализации определенных НТБ .

Remarks: Сообщение может быть многобайтовой строкой с завершающим нулем ([multibyte.strings]), подходящей для преобразования и отображения как wstring ([string.classes],[locale.codecvt]).

23.8.3 Class any [any.class]

class any {
public:
  // [any.cons], construction and destruction
  constexpr any() noexcept;

  any(const any& other);
  any(any&& other) noexcept;

  template <class T> any(T&& value);

  template <class T, class... Args>
    explicit any(in_place_type_t<T>, Args&&...);
  template <class T, class U, class... Args>
    explicit any(in_place_type_t<T>, initializer_list<U>, Args&&...);

  ~any();

  // [any.assign], assignments
  any& operator=(const any& rhs);
  any& operator=(any&& rhs) noexcept;

  template <class T> any& operator=(T&& rhs);

  // [any.modifiers], modifiers
  template <class T, class... Args>
    decay_t<T>& emplace(Args&& ...);
  template <class T, class U, class... Args>
    decay_t<T>& emplace(initializer_list<U>, Args&&...);
  void reset() noexcept;
  void swap(any& rhs) noexcept;

  // [any.observers], observers
  bool has_value() const noexcept;
  const type_info& type() const noexcept;
};

Объект классаany хранит экземпляр любого типа, который удовлетворяет требованиям конструктора или не имеет значения, и это называется объектомstate классаany . Сохраненный экземпляр называется.contained valueДва состояния эквивалентны, если либо они оба не имеют значения, либо оба имеют значение, а содержащиеся значения эквивалентны.

Функции, не являющиеся членами,any_­cast обеспечивают безопасный для типов доступ к содержащемуся значению.

Реализации должны избегать использования динамически выделяемой памяти для небольшого содержащегося значения. [ Example: где построенный объект содержит только файлint. ] Такая оптимизация малых объектов должна применяться только к типам, для которых есть .end exampleT is_­nothrow_­move_­constructible_­v<T> true

23.8.3.1 Construction and destruction [any.cons]

constexpr any() noexcept;

Postconditions: has_­value() естьfalse.

any(const any& other);

Effects: Еслиother.has_­value() естьfalse, создает объект, не имеющий значения. В противном случае эквивалентноany(in_­place<T>, any_­cast<const T&>(other)) гдеT - тип содержащегося объекта.

Throws: Любые исключения, возникающие при вызове выбранного конструктора для содержащегося значения.

any(any&& other) noexcept;

Effects: Еслиother.has_­value() естьfalse, создает объект, не имеющий значения. В противном случае создает объект типа,any который содержит либо содержащийся объектother, либо содержит объект того же типа, созданный из содержащегося объекта,other рассматривая этот содержащийся объект как rvalue.

Postconditions: other остается в допустимом, но в остальном неуказанном состоянии.

template<class T> any(T&& value);

ПустьVT будетdecay_­t<T>.

Requires: VT должны удовлетворятьCopyConstructible требованиям.

Effects: Создает объект типа,any который содержит объект типа,VT инициализированный напрямую с помощьюstd​::​forward<T>(value).

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если VT он не относится к тому же типу, что иany, VT не является специализациейin_­place_­type_­tи неis_­copy_­constructible_­v<VT> являетсяtrue.

Throws: Любое исключение, созданное выбранным конструкторомVT.

template <class T, class... Args> explicit any(in_place_type_t<T>, Args&&... args);

ПустьVT будетdecay_­t<T>.

Requires:VT должны удовлетворятьCopyConstructible требованиям.

Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования спискаVT с аргументамиstd​::​forward<Args>(args)....

Postconditions:*this содержит значение типаVT.

Throws: Любое исключение, созданное выбранным конструкторомVT.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­copy_­constructible_­v<VT> неtrue и is_­constructible_­v<VT, Args...> являетсяtrue.

template <class T, class U, class... Args> explicit any(in_place_type_t<T>, initializer_list<U> il, Args&&... args);

ПустьVT будетdecay_­t<T>.

Requires:VT должны удовлетворятьCopyConstructible требованиям.

Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования спискаVT с аргументамиil, std​::​forward<Args>(args)....

Postconditions:*this содержит значение.

Throws: Любое исключение, созданное выбранным конструкторомVT.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­copy_­constructible_­v<VT> неtrue и is_­constructible_­v<VT, initializer_­list<U>&, Args...> являетсяtrue.

~any();

Effects: Как будто мимоreset().

23.8.3.2 Assignment [any.assign]

any& operator=(const any& rhs);

Effects: Как будто мимоany(rhs).swap(*this). Никаких эффектов, если выбрасывается исключение.

Returns: *this.

Throws: Любые исключения, возникающие из конструктора копирования для содержащегося значения.

any& operator=(any&& rhs) noexcept;

Effects: Как будто мимоany(std​::​move(rhs)).swap(*this).

Returns: *this.

Postconditions: Состояние*this эквивалентно исходному состояниюrhs иrhs остается в допустимом, но в остальном не указанном состоянии.

template<class T> any& operator=(T&& rhs);

ПустьVT будетdecay_­t<T>.

Requires: VT должны удовлетворятьCopyConstructible требованиям.

Effects: Создает объектtmp типа,any который содержит объект типа,VT инициализированный напрямую с помощьюstd​::​forward<T>(rhs), иtmp.swap(*this). Никаких эффектов, если выбрасывается исключение.

Returns: *this.

Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если VT не является таким же типом , какany и is_­copy_­constructible_­v<VT> естьtrue.

Throws: Любое исключение, созданное выбранным конструкторомVT.

23.8.3.3 Modifiers [any.modifiers]

template <class T, class... Args> decay_t<T>& emplace(Args&&... args);

ПустьVT будетdecay_­t<T>.

Requires: VT должны удовлетворятьCopyConstructible требованиям.

Effects: Звонкиreset(). Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования спискаVT с аргументамиstd​::​forward<Args>(args)....

Postconditions:*this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструкторомVT.

Remarks: Если во время вызоваVTконструктора возникает исключение , *this он не содержит значения и любое ранее содержащееся значение было уничтожено. Эта функция не будет участвовать в разрешении перегрузки , если is_­copy_­constructible_­v<VT> неtrue и is_­constructible_­v<VT, Args...> являетсяtrue.

template <class T, class U, class... Args> decay_t<T>& emplace(initializer_list<U> il, Args&&... args);

ПустьVT будетdecay_­t<T>.

Requires: VT должны удовлетворятьCopyConstructible требованиям.

Effects: Звонкиreset(). Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования спискаVT с аргументами il, std​::​forward<Args>(args)....

Postconditions:*this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструкторомVT.

Remarks: Если во время вызоваVTконструктора возникает исключение , *this он не содержит значения и любое ранее содержащееся значение было уничтожено. Функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда is_­copy_­constructible_­v<VT> естьtrue и is_­constructible_­v<VT, initializer_­list<U>&, Args...> естьtrue.

void reset() noexcept;

Effects: Еслиhas_­value() естьtrue, уничтожает содержащееся значение.

Postconditions: has_­value() естьfalse.

void swap(any& rhs) noexcept;

Effects: Меняет состояния*this иrhs.

23.8.3.4 Observers [any.observers]

bool has_value() const noexcept;

Returns: true если*this содержит объект, в противном случаеfalse.

const type_info& type() const noexcept;

Returns: typeid(T) если*this имеет содержащееся значение типаT, в противном случаеtypeid(void).

[ Note: Полезно для запросов к типам, известным либо во время компиляции, либо только во время выполнения. ] end note

23.8.4 Non-member functions [any.nonmembers]

void swap(any& x, any& y) noexcept;

Effects: Как будто мимоx.swap(y).

template <class T, class... Args> any make_any(Args&& ...args);

Effects: Эквивалентен:return any(in_­place_­type<T>, std​::​forward<Args>(args)...);

template <class T, class U, class... Args> any make_any(initializer_list<U> il, Args&& ...args);

Effects: Эквивалентен:return any(in_­place_­type<T>, il, std​::​forward<Args>(args)...);

template<class T> T any_cast(const any& operand); template<class T> T any_cast(any& operand); template<class T> T any_cast(any&& operand);

ПозвольтеU быть типомremove_­cv_­t<remove_­reference_­t<ValueType>>.

Requires: Для первой перегрузкиis_­constructible_­v<ValueType, const U&> естьtrue. Для второй перегрузкиis_­constructible_­v<ValueType, U&> естьtrue. Для третьей перегрузкиis_­constructible_­v<ValueType, U> естьtrue. В противном случае программа будет некорректной.

Returns: Для первой и второй перегрузкиstatic_­cast<ValueType>(*any_­cast<U>(&operand)). Для третьей перегрузкиstatic_­cast<ValueType>(std​::​move(*any_­cast<U>(&operand))).

Throws: bad_­any_­cast еслиoperand.type() != typeid(remove_­reference_­t<T>).

[Example:

any x(5);                                   // x holds int
assert(any_cast<int>(x) == 5);              // cast to value
any_cast<int&>(x) = 10;                     // cast to reference
assert(any_cast<int>(x) == 10);

x = "Meow";                                 // x holds const char*
assert(strcmp(any_cast<const char*>(x), "Meow") == 0);
any_cast<const char*&>(x) = "Harry";
assert(strcmp(any_cast<const char*>(x), "Harry") == 0);

x = string("Meow");                         // x holds string
string s, s2("Jane");
s = move(any_cast<string&>(x));             // move from any
assert(s == "Meow");
any_cast<string&>(x) = move(s2);            // move to any
assert(any_cast<const string&>(x) == "Jane");

string cat("Meow");
const any y(cat);                           // const y holds string
assert(any_cast<const string&>(y) == cat);

any_cast<string&>(y);                       // error; cannot
                                            // any_­cast away const

end example]

template<class T> const T* any_cast(const any* operand) noexcept; template<class T> T* any_cast(any* operand) noexcept;

Returns: Еслиoperand != nullptr && operand->type() == typeid(T), указатель на объект, содержащийся вoperand; в противном случаеnullptr.

[Example:

bool is_string(const any& operand) {
  return any_cast<string>(&operand) != nullptr;
}

end example]