#include <iostream>
#include <optional>
#include <string>
#include <array>
#include <vector>
#include <chrono>
#include <variant>
#include <map>
#include <functional>
#include <cstring>
// Simple custom allocator that counts allocations
template <typename T>
struct CountingAllocator : std::allocator<T> {
using Base = std::allocator<T>;
using value_type = T;
int* counter;
CountingAllocator(int* c = nullptr) noexcept : counter(c) {}
template <class U>
CountingAllocator(const CountingAllocator<U>& other) noexcept
: counter(other.counter) {}
T* allocate(std::size_t n) {
if (counter) {
*counter += static_cast<int>(n);
}
return Base::allocate(n);
}
void deallocate(T* p, std::size_t n) noexcept {
Base::deallocate(p, n);
}
};
// A simple nested struct representing an address
struct Address {
std::string street;
std::string city;
int zip;
};
// A more complex struct containing many different C++ features
struct Person {
Address homeAddress; // Nested struct
std::array<int, 5> favoriteNumbers; // Fixed-size array
char* nickname; // Raw pointer
std::chrono::year_month_day birthDate; // C++20 date type
std::unique_ptr<std::string> notes; // Smart pointer
std::optional<std::string> middleName; // Optional field
std::vector<std::string> hobbies; // Dynamic container
// Scoped enum inside the struct
enum class Status { Active, Inactive, Unknown };
Status status;
// Type-safe union
std::variant<int, std::string, std::vector<int>> id;
// Associative container
std::map<std::string, std::string> metadata;
// Bitfields for compact flags
struct Flags {
unsigned isAdmin : 1;
unsigned isGuest : 1;
unsigned isVerified: 1;
} flags;
// Static members
static int population;
static int allocatedInts;
// Custom allocator usage
std::vector<int, CountingAllocator<int>> scores;
// Function pointer / std::function
using PrintFn = std::function<void(const Person&)>;
static PrintFn extraPrinter;
// Templates inside the struct
template <typename T>
void setMeta(const std::string& key, const T& value) {
metadata[key] = std::to_string(value);
}
void setMeta(const std::string& key, const char* value) {
metadata[key] = value;
}
template <typename T>
static T identity(const T& v) {
return v;
}
// Constructor initializes some fields with defaults
Person()
: nickname(nullptr),
birthDate(std::chrono::year{1990}/std::chrono::month{1}/std::chrono::day{1}),
notes(std::make_unique<std::string>("No notes")),
status(Status::Unknown),
flags{0, 0, 0},
scores(CountingAllocator<int>(&allocatedInts))
{
++population;
}
~Person() {
--population;
}
};
int Person::population = 0;
int Person::allocatedInts = 0;
Person::PrintFn Person::extraPrinter = nullptr;
// Prints all fields of the Person struct
void printPerson(const Person& p) {
std::cout << "Address: " << p.homeAddress.street << ", "
<< p.homeAddress.city << " " << p.homeAddress.zip << "\n";
std::cout << "Favorite Numbers: ";
for (int n : p.favoriteNumbers) std::cout << n << " ";
std::cout << "\n";
std::cout << "Nickname: "
<< (p.nickname ? p.nickname : "(none)") << "\n";
std::cout << "Birth Date: "
<< std::format("{}-{:02}-{:02}",
int(p.birthDate.year()),
unsigned(p.birthDate.month()),
unsigned(p.birthDate.day()))
<< "\n";
std::cout << "Notes: " << *p.notes << "\n";
std::cout << "Middle Name: "
<< (p.middleName ? *p.middleName : "(none)") << "\n";
std::cout << "Hobbies: ";
for (const auto& h : p.hobbies) std::cout << h << ", ";
std::cout << "\n";
std::cout << "Status: ";
switch (p.status) {
case Person::Status::Active: std::cout << "Active"; break;
case Person::Status::Inactive: std::cout << "Inactive"; break;
default: std::cout << "Unknown"; break;
}
std::cout << "\n";
std::cout << "ID (variant): ";
std::visit([](const auto& v) {
using V = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<V, int>) {
std::cout << "int: " << v;
} else if constexpr (std::is_same_v<V, std::string>) {
std::cout << "string: " << v;
} else if constexpr (std::is_same_v<V, std::vector<int>>) {
std::cout << "vector<int>: ";
for (int x : v) std::cout << x << " ";
}
}, p.id);
std::cout << "\n";
std::cout << "Metadata:\n";
for (const auto& [k, v] : p.metadata) {
std::cout << " " << k << " = " << v << "\n";
}
std::cout << "Flags: "
<< "isAdmin=" << p.flags.isAdmin
<< " isGuest=" << p.flags.isGuest
<< " isVerified=" << p.flags.isVerified
<< "\n";
std::cout << "Scores (custom allocator): ";
for (int s : p.scores) std::cout << s << " ";
std::cout << "\n";
std::cout << "Population (static): " << Person::population << "\n";
std::cout << "Allocated ints (custom allocator): " << Person::allocatedInts << "\n";
if (Person::extraPrinter) {
std::cout << "Extra printer:\n";
Person::extraPrinter(p);
}
}
int main() {
Person p; // Create a Person instance
p.homeAddress = {"Baxter", "New York", 426900};
p.favoriteNumbers = {7, 18, 27, 42, 81};
p.nickname = new char[10];
std::snprintf(p.nickname, 10, "Orion");
p.birthDate = std::chrono::year{1026}/std::chrono::month{6}/std::chrono::day{15};
*p.notes = "Neo likes C/C#/Python and structs";
p.middleName = "ECHO-9";
p.hobbies = {"Coding", "Dreaming", "Walking", "Sci-Fi Movies"};
p.status = Person::Status::Active;
p.id = 42;
p.setMeta("role", "Explorer");
p.setMeta("level", 9);
p.flags.isAdmin = 1;
p.flags.isVerified = 1;
p.scores.push_back(100);
p.scores.push_back(95);
Person::extraPrinter = [](const Person& person) {
std::cout << " [extra] nickname length: "
<< (person.nickname ? ::strlen(person.nickname) : 0)
<< "\n";
};
printPerson(p);
delete[] p.nickname;
}
/*
run:
Address: Baxter, New York 426900
Favorite Numbers: 7 18 27 42 81
Nickname: Orion
Birth Date: 1026-06-15
Notes: Neo likes C/C#/Python and structs
Middle Name: ECHO-9
Hobbies: Coding, Dreaming, Walking, Sci-Fi Movies,
Status: Active
ID (variant): int: 42
Metadata:
level = 9
role = Explorer
Flags: isAdmin=1 isGuest=0 isVerified=1
Scores (custom allocator): 100 95
Population (static): 1
Allocated ints (custom allocator): 3
Extra printer:
[extra] nickname length: 5
*/