std::any::any(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’– NAME πŸ’–

okay so bestie, welcome to std::any::any(3) from the C++ Standard Libary (yes, the header really spells it like that, and honestly? iconic typo energy πŸ’…). The NAME up top is literally std::any::any β€” std::any::any, no cap. This page is all about constructing a new any object. ✨


🌸 Synopsis 🌸

Here's the overload lineup, and every single one is (since C++17):

  • (1) (since C++17)
constexpr any() noexcept;
  • (2) (since C++17)
any( const any& other );
  • (3) (since C++17)
any( any&& other ) noexcept;
  • (4) (since C++17)
template< class ValueType >
any( ValueType&& value );
  • (5) (since C++17)
template< class ValueType, class... Args >
explicit any( std::in_place_type_t<ValueType>, Args&&... args );
  • (6) (since C++17)
template< class ValueType, class U, class... Args >
explicit any( std::in_place_type_t<ValueType>,
               std::initializer_list<U> il,
               Args&&... args );

Constructs a new any object. that's the whole assignment, and here's what each overload is giving:

  1. (1) β€” Constructs an empty object. empty. blank. a little blank-slate moment. πŸ’€
  2. (2) and (3) together β€” Copies (2) or moves (3) the content of other into a new instance, so that any content is equivalent in both type and value to those of other prior to the constructor call, or empty if other is empty. formally:
    • (2) β€” If other is empty, the constructed object is empty. Otherwise, equivalent to any(std::in_place_type<T>, std::any_cast<const T&>(other)), where T is the type of the object contained in other.
    • (3) β€” If other is empty, the constructed object is empty. Otherwise, the constructed object contains either the object contained in other, or an object of the same type constructed from the object contained in other, considering that object as an rvalue.
  3. (4) β€” Constructs an object with initial content an object of type std::decay_t<ValueType>, direct-initialized from std::forward<ValueType>(value).
    • This overload participates in overload resolution only if std::decay_t<ValueType> is not the same type as any nor a specialization of std::in_place_type_t, and std::is_copy_constructible_v<std::decay_t<ValueType>> is true.
  4. (5) β€” Constructs an object with initial content an object of type std::decay_t<ValueType>, direct-non-list-initialized from std::forward<Args>(args)....
    • This overload participates in overload resolution only if std::is_constructible_v<std::decay_t<ValueType>, Args...> and std::is_copy_constructible_v<std::decay_t<ValueType>> are both true.
  5. (6) β€” Constructs an object with initial content an object of type std::decay_t<ValueType>, direct-non-list-initialized from il, std::forward<Args>(args)....
    • This overload participates in overload resolution only if std::is_constructible_v<std::decay_t<ValueType>, std::initializer_list<U>&, Args...> and std::is_copy_constructible_v<std::decay_t<ValueType>> are both true.

🧚 Template parameters 🧚

  • ValueType β€” contained value type. that's the type tucked inside the any, periodt. πŸ’œ

πŸŽ€ Type requirements πŸŽ€

  • std::decay_t<ValueType> must meet the requirements of CopyConstructible.

πŸ¦‹ Parameters πŸ¦‹

  • other β€” another any object to copy or move from
  • value β€” value to initialize the contained value with
  • il, args β€” arguments to be passed to the constructor of the contained object

πŸ”₯ Exceptions πŸ”₯

  • 2,4-6) β€” Throws any exception thrown by the constructor of the contained type. so if the contained type's constructor is dramatic, this constructor is dramatic too 😭

πŸ’œ Notes πŸ’œ

Because the default constructor is constexpr, static std::anys are initialized as part of static non-local initialization, before any dynamic non-local initialization begins. This makes it safe to use an object of type std::any in a constructor of any static object. no cap, that's the whole note. 🫢


🌈 Example 🌈

Run this code, bestie:

#include <boost/core/demangle.hpp>

#include <any>
#include <initializer_list>
#include <iostream>
#include <memory>
#include <set>
#include <string>
#include <utility>

struct A
{
    int age;
    std::string name;
    double salary;

#if __cpp_aggregate_paren_init < 201902L
    // Required before C++20 for in-place construction
    A(int age, std::string name, double salary)
        : age(age), name(std::move(name)), salary(salary) {}
#endif
};

// Using abi demangle to print nice type name of instance of any holding
void printType(const std::any& a)
{
    std::cout << boost::core::demangle(a.type().name()) << '\n';
}

int main()
{
    // Constructor #4: std::any holding int
    std::any a1{7};

    // Constructor #5: std::any holding A, constructed in place
    std::any a2(std::in_place_type<A>, 30, "Ada", 1000.25);

    // Constructor #6: std::any holding a set of A with custom comparison
    auto lambda = [](auto&& l, auto&& r){ return l.age < r.age; };
    std::any a3(
        std::in_place_type<std::set<A, decltype(lambda)>>,
        {
            A{39, std::string{"Ada"}, 100.25},
            A{20, std::string{"Bob"}, 75.5}
        },
        lambda);

    printType(a1);
    printType(a2);
    printType(a3);
}

Possible output:

int
A
std::set<A, main::{lambda(auto:1&&, auto:2&&)#1}, std::allocator<A> >

πŸ‘‘ See also πŸ‘‘

  • operator= β€” assigns an any object (public member function)

🫢 that's the tea, bestie β€” sourced from http://cppreference.com, version/date 2024.06.10, page std::any::any(3). now go construct something iconic πŸ’…
πŸ“¦ where this page comes from