22 General utilities library [utilities]
22.7 Storage for any type [any]
Subclause [any] describes components that C++ programs may use to perform operations on objects of a discriminated type
.[
Note 1:
The discriminated type can 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]
namespace std {
class bad_any_cast;
class any;
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;
}
namespace std {
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.const char* what() const noexcept override;
Returns: An
implementation-defined
ntbs. namespace std {
class any {
public:
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& operator=(const any& rhs);
any& operator=(any&& rhs) noexcept;
template<class T>
any& operator=(T&& rhs);
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;
bool has_value() const noexcept;
const type_info& type() const noexcept;
};
}
An object of class
any stores an instance of any type that meets the constructor requirements or it has no value,
and this is referred to as the
state of the class
any object
. Two states are equivalent if either they both have no value, or they both have a value and the contained values are equivalent
.The non-member
any_cast functions provide type-safe access to the contained value
.Implementations should avoid the use of dynamically allocated memory for a small contained value
. However, any such small-object optimization shall only be applied to types
T for which
is_nothrow_move_constructible_v<T> is
true. [
Example 1:
A contained value of type
int could be stored in an internal buffer,
not in separately-allocated memory
. —
end example]
constexpr any() noexcept;
Postconditions:
has_value() is
false. Effects: If
other.has_value() is
false, constructs an object that has no value
. Otherwise, equivalent to
any(in_place_type<T>, any_cast<const T&>(other))
where
T is the type of the contained value
.Throws: Any exceptions arising from calling the selected constructor for the contained value
. any(any&& other) noexcept;
Effects: If
other.has_value() is
false, constructs an object that has no value
. Otherwise, constructs an object of type
any that
contains either the contained value of
other, or
contains an object of the same type constructed from
the contained value of
other considering that contained value as an rvalue
.template<class T>
any(T&& value);
Constraints:
VT is not the same type as
any,
VT is not a specialization of
in_place_type_t,
and
is_copy_constructible_v<VT> is
true. Effects: Constructs an object of type
any that contains an object of type
VT direct-initialized with
std::forward<T>(value). Throws: Any exception thrown by the selected constructor of
VT. template<class T, class... Args>
explicit any(in_place_type_t<T>, Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, Args...> is
true. Effects: Direct-non-list-initializes the contained value of type
VT
with
std::forward<Args>(args).... Postconditions:
*this contains a value of type
VT. Throws: Any exception thrown by the selected constructor of
VT. template<class T, class U, class... Args>
explicit any(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, initializer_list<U>&, Args...> is
true. Effects: Direct-non-list-initializes the contained value of type
VT
with
il, std::forward<Args>(args).... Postconditions:
*this contains a value
. Throws: Any exception thrown by the selected constructor of
VT. Effects: As if by
reset(). any& operator=(const any& rhs);
Effects: As if by
any(rhs).swap(*this). No effects if an exception is thrown
.Throws: Any exceptions arising from the copy constructor for the contained value
. any& operator=(any&& rhs) noexcept;
Effects: As if by
any(std::move(rhs)).swap(*this). Postconditions: The state of
*this is equivalent to the original state of
rhs. template<class T>
any& operator=(T&& rhs);
Constraints:
VT is not the same type as
any and
is_copy_constructible_v<VT> is
true. Effects: Constructs an object
tmp of type
any that contains an object of type
VT direct-initialized with
std::forward<T>(rhs), and
tmp.swap(*this). No effects if an exception is thrown
.Throws: Any exception thrown by the selected constructor of
VT. template<class T, class... Args>
decay_t<T>& emplace(Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, Args...> is
true. Then direct-non-list-initializes the contained value of type
VT
with
std::forward<Args>(args).... Postconditions:
*this contains a value
. Returns: A reference to the new contained value
. Throws: Any exception thrown by the selected constructor of
VT. Remarks: If an exception is thrown during the call to
VT's constructor,
*this does not contain a value, and any previously contained value
has been destroyed
. template<class T, class U, class... Args>
decay_t<T>& emplace(initializer_list<U> il, Args&&... args);
Constraints:
is_copy_constructible_v<VT> is
true and
is_constructible_v<VT, initializer_list<U>&, Args...> is
true. Then direct-non-list-initializes the contained value
of type
VT with
il, std::forward<Args>(args).... Postconditions:
*this contains a value
. Returns: A reference to the new contained value
. Throws: Any exception thrown by the selected constructor of
VT. Remarks: If an exception is thrown during the call to
VT's constructor,
*this does not contain a value, and any previously contained value
has been destroyed
. Effects: If
has_value() is
true, destroys the contained value
. Postconditions:
has_value() is
false. void swap(any& rhs) noexcept;
Effects: Exchanges the states of
*this and
rhs. 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 value of type
T,
otherwise
typeid(void). [
Note 1:
Useful for querying against types known either at compile time or only at runtime
. —
end note]
void swap(any& x, any& y) noexcept;
Effects: Equivalent to
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 T>
T any_cast(const any& operand);
template<class T>
T any_cast(any& operand);
template<class T>
T any_cast(any&& operand);
Let
U be the type
remove_cvref_t<T>.Mandates: For the first overload,
is_constructible_v<T, const U&> is
true. For the second overload,
is_constructible_v<T, U&> is
true. For the third overload,
is_constructible_v<T, U> is
true.Returns: For the first and second overload,
static_cast<T>(*any_cast<U>(&operand)). For the third overload,
static_cast<T>(std::move(*any_cast<U>(&operand))).Throws:
bad_any_cast if
operand.type() != typeid(remove_reference_t<T>). [
Example 1:
any x(5);
assert(any_cast<int>(x) == 5);
any_cast<int&>(x) = 10;
assert(any_cast<int>(x) == 10);
x = "Meow";
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");
string s, s2("Jane");
s = move(any_cast<string&>(x));
assert(s == "Meow");
any_cast<string&>(x) = move(s2);
assert(any_cast<const string&>(x) == "Jane");
string cat("Meow");
const any y(cat);
assert(any_cast<const string&>(y) == cat);
any_cast<string&>(y);
—
end example]
template<class T>
const T* any_cast(const any* operand) noexcept;
template<class T>
T* any_cast(any* operand) noexcept;
Mandates:
is_void_v<T> is
false. Returns: If
operand != nullptr && operand->type() == typeid(T) is
true,
a pointer to the object contained by
operand;
otherwise,
nullptr. [
Example 2:
bool is_string(const any& operand) {
return any_cast<string>(&operand) != nullptr;
}
—
end example]