20 General utilities library [utilities]

20.8 Storage for any type [any]

This section describes components that C++ programs may use to perform operations on objects of a discriminated type.

Note: The discriminated type may contain values of different types but does not attempt conversion between them, i.e. 5 is held strictly as an int and is not implicitly convertible either to "5" or to 5.0. This indifference to interpretation but awareness of type effectively allows safe, generic containers of single values, with no scope for surprises from ambiguous conversions.  — end note ]

20.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 ValueType>
    ValueType any_cast(const any& operand);
  template<class ValueType>
    ValueType any_cast(any& operand);
  template<class ValueType>
    ValueType any_cast(any&& operand);
  
  template<class ValueType>
    const ValueType* any_cast(const any* operand) noexcept;
  template<class ValueType>
    ValueType* any_cast(any* operand) noexcept;
}

20.8.2 Class bad_any_cast [any.bad_any_cast]

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

Objects of type bad_any_cast are thrown by a failed any_cast ([any.nonmembers]).

20.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 ValueType> any(ValueType&& value);

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

  ~any();

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

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

  // [any.modifiers], modifiers
  template <class ValueType, class... Args>
    void emplace(Args&& ...);
  template <class ValueType, class U, class... Args>
    void 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;
};

An object of class any stores an instance of any type that satisfies the constructor requirements or it has no value, and this is referred to as the state of the class any object. The stored instance is called the contained object. Two states are equivalent if either they both have no value, or both have a value and the contained objects are equivalent.

The non-member any_cast functions provide type-safe access to the contained object.

Implementations should avoid the use of dynamically allocated memory for a small contained object. [ Example: where the object constructed is holding only an int.  — end example ] Such small-object optimization shall only be applied to types T for which is_nothrow_move_constructible_v<T> is true.

20.8.3.1 Construction and destruction [any.cons]

constexpr any() noexcept;

Postconditions: has_value() is false.

any(const any& other);

Effects: Constructs an object of type any with an equivalent state as other.

Throws: Any exceptions arising from calling the selected constructor of the contained object.

any(any&& other) noexcept;

Effects: Constructs an object of type any with a state equivalent to the original state of other.

Postconditions: other is left in a valid but otherwise unspecified state.

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

Let T be decay_t<ValueType>.

Requires: T shall satisfy the CopyConstructible requirements.

Effects: Constructs an object of type any that contains an object of type T direct-initialized with std::forward<ValueType>(value).

Remarks: This constructor shall not participate in overload resolution unless T is not the same type as any, T is not a specialization of in_place_type_t, and is_copy_constructible_v<T> is true.

Throws: Any exception thrown by the selected constructor of T.

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

Let T be decay_t<ValueType>.

Requires: T shall satisfy the CopyConstructible requirements.

Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....

Postconditions: *this contains a value of type T.

Throws: Any exception thrown by the selected constructor of T.

Remarks: This constructor shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

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

Let T be decay_t<ValueType>.

Requires: T shall satisfy the CopyConstructible requirements.

Effects: Initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args>(args)....

Postconditions: *this contains a value.

Throws: Any exception thrown by the selected constructor of T.

Remarks: This constructor shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

~any();

Effects: As if by reset().

20.8.3.2 Assignment [any.assign]

any& operator=(const any& rhs);

Effects: As if by any(rhs).swap(*this). No effects if an exception is thrown.

Returns: *this.

Throws: Any exceptions arising from the copy constructor of the contained object.

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

Effects: As if by any(std::move(rhs)).swap(*this).

Returns: *this.

Postconditions: The state of *this is equivalent to the original state of rhs and rhs is left in a valid but otherwise unspecified state.

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

Let T be decay_t<ValueType>.

Requires: T shall satisfy the CopyConstructible requirements.

Effects: Constructs an object tmp of type any that contains an object of type T direct-initialized with std::forward<ValueType>(rhs), and tmp.swap(*this). No effects if an exception is thrown.

Returns: *this.

Remarks: This operator shall not participate in overload resolution unless T is not the same type as any and is_copy_constructible_v<T> is true.

Throws: Any exception thrown by the selected constructor of T.

20.8.3.3 Modifiers [any.modifiers]

template <class ValueType, class... Args> void emplace(Args&&... args);

Let T be decay_t<ValueType>.

Requires: T shall satisfy the CopyConstructible requirements.

Effects: Calls reset(). Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args)....

Postconditions: *this contains a value.

Throws: Any exception thrown by the selected constructor of T.

Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. This function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

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

Let T be decay_t<ValueType>.

Requires: T shall satisfy the CopyConstructible requirements.

Effects: Calls reset(). Then initializes the contained value as if direct-non-list-initializing an object of type T with the arguments il, std::forward<Args> (args)....

Postconditions: *this contains a value.

Throws: Any exception thrown by the selected constructor of T.

Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. The function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

void reset() noexcept;

Effects: If has_value() is true, destroys the contained object.

Postconditions: has_value() is false.

void swap(any& rhs) noexcept;

Effects: Exchanges the states of *this and rhs.

20.8.3.4 Observers [any.observers]

bool has_value() const noexcept;

Returns: true if *this contains an object, otherwise false.

const type_info& type() const noexcept;

Returns: typeid(T) if *this has a contained object of type T, otherwise typeid(void).

Note: Useful for querying against types known either at compile time or only at runtime.  — end note ]

20.8.4 Non-member functions [any.nonmembers]

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

Effects: As if by x.swap(y).

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

Effects: Equivalent to: 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: Equivalent to: return any(in_place_type<T>, il, std::forward<Args>(args)...);

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

Requires: is_reference_v<ValueType> is true or is_copy_constructible_v<ValueType> is true. Otherwise the program is ill-formed.

Returns: For the first form, *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand). For the second and third forms, *any_cast<remove_reference_t<ValueType>>(&operand).

Throws: bad_any_cast if operand.type() != typeid(remove_reference_t<ValueType>).

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 ValueType> const ValueType* any_cast(const any* operand) noexcept; template<class ValueType> ValueType* any_cast(any* operand) noexcept;

Returns: If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object contained by operand; otherwise, nullptr.

Example:

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

 — end example ]