vibe coding 40 分钟完成了超酷的 stack

GPT-5 到底有多强?

我这里不说废话,这是我和它协作40分钟的结果。

代码应当在 GPLv3.0 下发布,但是我不方便建立 GitHub 仓库提供副本,所以许可证的文件请见:https://www.gnu.org/licenses/

提示词如下:

让我们来写一个 Stack 类,用 C++ 23!
1. 使用 template <typename... Types> 配合 std::variant 和 std::visit 解决对齐和类型安全的问题
2. 支持标准库风格的迭代器
3. 使用 std::construct_at 和 std::destroy_at 手动管理对象存在周期,避免不必要的开销
4. 兼容 pmr 和 allocator,支持修改分配策略
5. 使用 concept 明确地定义相关的需求,避免模板天书
做得非常棒,我们现在进行迭代:
1. 检查展开模板参数包的问题
[compiler log ...]
2. 除非必要,使用`and``or`等风格的逻辑运算符,不要使用老式C风格的逻辑运算符
3. 使用 Doxygen 风格的注释,可以详细地说明;注释信息中英双语
4. 考虑到日常使用,应该在合适的位置设置好默认参数,并且尽可能地让模板参数能够自行推导
别急,来修 bug!
[compiler log ...]
这次更新,我们迭代这几个:
1. 引入 noexcept(move) 颗粒度的更细异常保证
2. 提供 small_buffer 小对象优化版本
3. 加强可行范围内的 static reflection,对基础类型和对齐可解决的小类型进行优化
维持设计需求不变(也就是已有的设计语义约束),我们来修 Bug:
[compiler log ...]
嗯,我觉得很不错,你很棒!
接下来的任务:生成一份测试代码,饱和性质地测试一遍我们的 stack;只写在 main 函数中。
嗯,你的测试代码有问题,修复一下bug:
[compiler log ...]

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2025 azureveil <azureveil4295@yeah.net>
//
// This file is part of azureveil stack demo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include <variant>
#include <memory>
#include <memory_resource>
#include <type_traits>
#include <concepts>
#include <iterator>
#include <utility>
#include <new>
#include <cstddef>
#include <stdexcept>
#include <algorithm>
#include <initializer_list>
#include <array>
#include <cstring> // memcpy
#include <cassert>

namespace tools
{
    /**
     * @brief A type-list for meta programming. / 用于元编程的类型列表
     */
    template <class... Ts>
    struct type_list
    {
    };

    /* ========================= Concepts(概念)========================= */

    /**
     * @brief Check T is in pack Ts...  / 判断类型 T 是否在 Ts... 中
     */
    template <class T, class... Ts>
    concept InPack = (std::same_as<std::remove_cvref_t<T>, Ts> or ...);

    /**
     * @brief Element pack requirements for stack. / 栈的候选类型包需求
     * - every type is destructible and move-constructible
     * - pack size > 0
     *
     * 重要:折叠表达式必须写成 ((A and B) and ...),避免编译器报
     * "binary expression in operand of fold-expression"。
     */
    template <class... Ts>
    concept StackElementPack =
        ((std::destructible<Ts> and std::move_constructible<Ts>) and ...) and (sizeof...(Ts) > 0);

    /**
     * @brief Allocator can be rebound to T. / 分配器可重绑定到 T
     */
    template <class Alloc, class T>
    concept RebindableAllocator = requires {
        typename std::allocator_traits<Alloc>::template rebind_alloc<T>;
    };

    /**
     * @brief f is a valid visitor for std::variant<Ts...>. / 访问器概念
     */
    template <class F, class... Ts>
    concept VariantVisitor =
        requires(F f, std::variant<Ts...> &v) { std::visit(f, v); } and
        requires(F f, const std::variant<Ts...> &cv) { std::visit(f, cv); };

    /* ========================= meta: unique types ===================== */

    namespace detail
    {

        /**
         * @brief contains<List, T> -> bool_constant  / 判断 T 是否在 type_list 中
         */
        template <class List, class T>
        struct contains;

        template <class T>
        struct contains<type_list<>, T> : std::false_type
        {
        };

        template <class Head, class... Tail, class T>
        struct contains<type_list<Head, Tail...>, T>
            : std::conditional_t<std::same_as<Head, T>, std::true_type, contains<type_list<Tail...>, T>>
        {
        };

        /**
         * @brief prepend<List, T>  / 在列表前部插入
         */
        template <class List, class T>
        struct prepend;

        template <class... Ts, class T>
        struct prepend<type_list<Ts...>, T>
        {
            using type = type_list<T, Ts...>;
        };

        /**
         * @brief unique_types<Ts...> 去重并保持首次出现顺序 / make unique, keep first-appearance order
         */
        template <class... Ts>
        struct unique_types;

        template <>
        struct unique_types<>
        {
            using type = type_list<>;
        };

        template <class T, class... Rest>
        struct unique_types<T, Rest...>
        {
            using rest = typename unique_types<Rest...>::type;
            static constexpr bool in = contains<rest, T>::value;
            using type = std::conditional_t<in, rest, typename prepend<rest, T>::type>;
        };

        /**
         * @brief forward decl: to_basic_stack<Alloc, type_list<...>>
         * 仅声明,不定义,避免重定义冲突!
         */
        template <class Alloc, class List>
        struct to_basic_stack;

    } // namespace detail

    /* ========================= basic_stack with SBO =================== */

    /**
     * @class basic_stack
     * @brief A type-safe, allocator-aware multi-type stack based on std::variant,
     *        with optional Small Buffer Optimization (SBO).
     *        使用 std::variant 的类型安全、分配器友好、可选小对象优化(SBO)的多类型栈。
     *
     * @tparam Allocator  allocator type (defaults to std::allocator<std::byte>)
     *                    分配器类型(默认 std::allocator<std::byte>)
     * @tparam SBO        inline capacity in elements for small-buffer optimization
     *                    小对象优化的内联容量(按元素个数)
     * @tparam Types...   element alternative types (non-empty pack)
     *                    备选元素类型(非空包)
     *
     * # Design highlights / 设计要点
     * - Storage is `std::variant<Types...>` for type-safety & alignment.(对齐与类型安全由 variant 保证)
     * - Manual lifetime with `std::construct_at` / `std::destroy_at`.(手动控制对象生命周期)
     * - Standard-style iterators (contiguous).(标准库风格迭代器,连续存储)
     * - Supports PMR 和常规分配器。/ Supports PMR and regular allocators.
     * - `noexcept(move)` granular policy: relocation chooses move-or-copy by traits. /
     *    基于类型性质(traits)选择“移动或拷贝”,提供细粒度异常保证。
     * - SBO: small sizes live on-stack; larger spill to heap. / 小容量走栈上内联,大容量溢出到堆。
     *
     * @note 对“静态反射(static reflection)”的可行优化:
     *  - 若 `storage_type`(即 `std::variant<Ts...>`)满足
     *    `std::is_trivially_copyable_v`,则迁移使用 `memcpy` 快路径;
     *  - 否则若 `std::is_nothrow_move_constructible_v<storage_type>`,则采用移动构造;
     *  - 否则退化为拷贝构造,保持强异常保证(strong exception safety)。
     */
    template <
        class Allocator = std::allocator<std::byte>,
        std::size_t SBO = 0,
        class... Types>
        requires StackElementPack<Types...> and RebindableAllocator<Allocator, std::variant<Types...>>
    class basic_stack
    {
    public:
        using storage_type = std::variant<Types...>;
        using value_type = storage_type;
        using allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<storage_type>;
        using allocator_traits = std::allocator_traits<allocator_type>;

        using size_type = std::size_t;
        using difference_type = std::ptrdiff_t;

        using reference = storage_type &;
        using const_reference = const storage_type &;
        using pointer = storage_type *;
        using const_pointer = const storage_type *;

        using iterator = storage_type *;
        using const_iterator = const storage_type *;
        using reverse_iterator = std::reverse_iterator<iterator>;
        using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    private:
        // ---- Static reflection knobs / 静态性质开关 ----
        static constexpr bool triv_copyable = std::is_trivially_copyable_v<storage_type>;
        static constexpr bool triv_destruct = std::is_trivially_destructible_v<storage_type>;
        static constexpr bool nothrow_move = std::is_nothrow_move_constructible_v<storage_type>;
        static constexpr std::size_t TSize = sizeof(storage_type);
        static constexpr std::size_t TAlign = alignof(storage_type);
        static constexpr bool has_sbo = (SBO > 0);

        /// @brief SBO 内联块(仅在 has_sbo 为真时作为候选)/ inline storage when SBO enabled
        struct alignas(TAlign) sbo_block
        {
            std::array<std::byte, SBO * TSize> buf{};
        };

        /// @brief 无 SBO 时的占位类型(空壳)/ empty placeholder when SBO disabled
        struct no_sbo_block
        {
        };

        /// @brief 依据 has_sbo 选择实际的 sbo_ 成员类型
        using sbo_storage_t = std::conditional_t<has_sbo, sbo_block, no_sbo_block>;

    public:
        /* ------------- constructors / 构造与析构 ------------- */

        /**
         * @brief Default ctor (uses SBO if available, otherwise no allocation).
         *        默认构造(若启用 SBO 则指向内联缓冲,否则不分配)
         */
        basic_stack() noexcept(noexcept(allocator_type{}))
            : alloc_{}, data_{init_data_ptr_()}, size_{0}, cap_{init_cap_()} {}

        /**
         * @brief Construct with allocator. / 指定分配器构造
         */
        explicit basic_stack(const Allocator &a)
            : alloc_{rebind_alloc_(a)}, data_{init_data_ptr_()}, size_{0}, cap_{init_cap_()} {}

        /**
         * @brief PMR resource ctor (enabled only for PMR allocator). /
         *        PMR 资源构造(仅当分配器为 PMR 时启用)
         */
        basic_stack(std::pmr::memory_resource *r)
            requires std::same_as<std::remove_cvref_t<Allocator>, std::pmr::polymorphic_allocator<std::byte>>
            : alloc_{allocator_type{r}}, data_{init_data_ptr_()}, size_{0}, cap_{init_cap_()}
        {
        }

        /**
         * @brief Reserve capacity upfront. / 预留容量的构造
         * @param reserve_cap initial capacity / 初始容量
         * @param a allocator (optional) / 可选分配器
         */
        explicit basic_stack(size_type reserve_cap, const Allocator &a = Allocator{})
            : alloc_{rebind_alloc_(a)}, data_{init_data_ptr_()}, size_{0}, cap_{init_cap_()}
        {
            if (reserve_cap > cap_)
                reserve(reserve_cap);
        }

        /**
         * @brief Construct from initializer_list of variants. / 从 variant 列表构造
         */
        basic_stack(std::initializer_list<storage_type> init, const Allocator &a = Allocator{})
            : alloc_{rebind_alloc_(a)}, data_{init_data_ptr_()}, size_{0}, cap_{init_cap_()}
        {
            reserve(init.size());
            for (auto const &v : init)
                push(v);
        }

        basic_stack(const basic_stack &other)
            : alloc_{allocator_traits::select_on_container_copy_construction(other.alloc_)}, data_{init_data_ptr_()}, size_{0}, cap_{init_cap_()}
        {
            reserve(other.size_);
            try
            {
                uninit_copy_n_(other.data_, other.size_, data_);
                size_ = other.size_;
            }
            catch (...)
            {
                destroy_n_(data_, size_);
                deallocate_if_heap_();
                throw;
            }
        }

        basic_stack(basic_stack &&other) noexcept
            : alloc_{std::move(other.alloc_)}, data_{init_data_ptr_()}, size_{0}, cap_{init_cap_()}
        {
            // 优先:若分配器“总是相等”,可直接窃取缓冲
            if constexpr (allocator_traits::is_always_equal::value)
            {
                if (other.using_heap_())
                {
                    data_ = other.data_;
                    cap_ = other.cap_;
                    size_ = other.size_;
                    other.data_ = other.inline_ptr_();
                    other.cap_ = other.init_cap_();
                    other.size_ = 0;
                    return;
                }
            }
            // PMR 特例:同一 resource 也可安全窃取
            else if constexpr (std::same_as<std::remove_cvref_t<Allocator>, std::pmr::polymorphic_allocator<std::byte>>)
            {
                if (other.using_heap_() and alloc_.resource() == other.alloc_.resource())
                {
                    data_ = other.data_;
                    cap_ = other.cap_;
                    size_ = other.size_;
                    other.data_ = other.inline_ptr_();
                    other.cap_ = other.init_cap_();
                    other.size_ = 0;
                    return;
                }
            }
        }

        basic_stack &operator=(const basic_stack &other)
        {
            if (this == &other)
                return *this;
            if constexpr (allocator_traits::propagate_on_container_copy_assignment::value)
            {
                if (alloc_ != other.alloc_)
                {
                    clear();
                    deallocate_if_heap_();
                }
                alloc_ = other.alloc_;
            }
            if (other.size_ > cap_)
            {
                reallocate_to_(other.size_);
            }
            // 赋值已有元素并填充/销毁多余
            const size_type common = std::min(size_, other.size_);
            for (size_type i = 0; i < common; ++i)
                data_[i] = other.data_[i];
            if (size_ < other.size_)
            {
                uninit_copy_n_(other.data_ + size_, other.size_ - size_, data_ + size_);
            }
            else
            {
                destroy_n_(data_ + other.size_, size_ - other.size_);
            }
            size_ = other.size_;
            return *this;
        }

        basic_stack &operator=(basic_stack &&other) noexcept(
            allocator_traits::propagate_on_container_move_assignment::value or
            std::is_nothrow_move_assignable_v<allocator_type>)
        {
            if (this == &other)
                return *this;
            if constexpr (allocator_traits::propagate_on_container_move_assignment::value)
            {
                clear();
                deallocate_if_heap_();
                alloc_ = std::move(other.alloc_);
                if (other.using_heap_())
                {
                    data_ = other.data_;
                    size_ = other.size_;
                    cap_ = other.cap_;
                    other.data_ = other.inline_ptr_();
                    other.size_ = 0;
                    other.cap_ = other.init_cap_();
                }
                else
                {
                    data_ = inline_ptr_();
                    cap_ = init_cap_();
                    size_ = 0;
                    reserve(other.size_);
                    uninit_move_or_copy_n_(other.data_, other.size_, data_);
                    size_ = other.size_;
                    other.clear();
                }
            }
            else
            {
                if (alloc_ == other.alloc_)
                {
                    clear();
                    deallocate_if_heap_();
                    if (other.using_heap_())
                    {
                        data_ = other.data_;
                        size_ = other.size_;
                        cap_ = other.cap_;
                        other.data_ = other.inline_ptr_();
                        other.size_ = 0;
                        other.cap_ = other.init_cap_();
                    }
                    else
                    {
                        data_ = inline_ptr_();
                        cap_ = init_cap_();
                        size_ = 0;
                        reserve(other.size_);
                        uninit_move_or_copy_n_(other.data_, other.size_, data_);
                        size_ = other.size_;
                        other.clear();
                    }
                }
                else
                {
                    assign_move_from_(other);
                }
            }
            return *this;
        }

        ~basic_stack()
        {
            destroy_n_(data_, size_);
            deallocate_if_heap_();
        }

        /* ------------- iterators / 迭代器 ------------- */

        /// @brief begin / 起始迭代器
        iterator begin() noexcept { return data_; }
        const_iterator begin() const noexcept { return data_; }
        const_iterator cbegin() const noexcept { return data_; }

        /// @brief end / 末尾迭代器
        iterator end() noexcept { return data_ + size_; }
        const_iterator end() const noexcept { return data_ + size_; }
        const_iterator cend() const noexcept { return data_ + size_; }

        /// @brief reverse begin / 反向起始
        reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
        const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
        const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator{end()}; }

        /// @brief reverse end / 反向末尾
        reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
        const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
        const_reverse_iterator crend() const noexcept { return const_reverse_iterator{begin()}; }

        /* ------------- capacity / 容量 ------------- */

        /// @brief empty? / 是否为空
        [[nodiscard]] bool empty() const noexcept { return size_ == 0; }

        /// @brief size / 当前大小
        [[nodiscard]] size_type size() const noexcept { return size_; }

        /// @brief capacity / 当前容量
        [[nodiscard]] size_type capacity() const noexcept { return cap_; }

        /// @brief reserve capacity / 预留容量
        void reserve(size_type new_cap)
        {
            if (new_cap <= cap_)
                return;
            reallocate_to_(new_cap);
        }

        /// @brief shrink to fit (may move back into SBO) / 收缩容量(可能回迁至 SBO)
        void shrink_to_fit()
        {
            if (size_ == cap_)
                return;
            const size_type target = size_;
            // 若启用 SBO 且可容纳,则回迁内联
            if constexpr (has_sbo)
            {
                if (target <= SBO)
                {
                    reallocate_to_(SBO);
                    return;
                }
            }
            reallocate_to_(target);
        }

        /// @brief clear (destroy all elements) / 清空(析构所有元素)
        void clear() noexcept
        {
            destroy_n_(data_, size_);
            size_ = 0;
        }

        /* ------------- element access / 访问 ------------- */

        /// @brief top (mutable) / 顶部元素(可变)
        reference top()
        {
            if (empty())
                throw std::out_of_range("stack is empty");
            return data_[size_ - 1];
        }
        /// @brief top (const) / 顶部元素(常量)
        const_reference top() const
        {
            if (empty())
                throw std::out_of_range("stack is empty");
            return data_[size_ - 1];
        }

        /**
         * @brief Visit top via visitor. / 使用访问器访问顶部元素
         */
        template <VariantVisitor<Types...> F>
        decltype(auto) visit_top(F &&f)
        {
            return std::visit(std::forward<F>(f), top());
        }
        template <VariantVisitor<Types...> F>
        decltype(auto) visit_top(F &&f) const
        {
            return std::visit(std::forward<F>(f), top());
        }

        /**
         * @brief Visit all elements. / 访问所有元素
         */
        template <VariantVisitor<Types...> F>
        void visit_all(F &&f)
        {
            for (auto &e : *this)
                std::visit(f, e);
        }
        template <VariantVisitor<Types...> F>
        void visit_all(F &&f) const
        {
            for (auto &e : *this)
                std::visit(f, e);
        }

        /* ------------- modifiers / 修改器 ------------- */

        /**
         * @brief Push a variant value. / 压入一个 variant 值
         */
        void push(value_type v)
        {
            ensure_growth_();
            std::construct_at(data_ + size_, std::move(v));
            ++size_;
        }

        /**
         * @brief Push a concrete alternative in Types... / 压入具体候选类型的值
         */
        template <class T>
            requires InPack<T, Types...>
        void push(T &&x)
        {
            ensure_growth_();
            std::construct_at(
                data_ + size_,
                std::in_place_type<std::remove_cvref_t<T>>,
                std::forward<T>(x));
            ++size_;
        }

        /**
         * @brief Emplace the top element as alternative T. / 原地构造指定候选类型 T 的顶部元素
         */
        template <class T, class... Args>
            requires InPack<T, Types...> and std::constructible_from<T, Args...>
        reference emplace(Args &&...args)
        {
            ensure_growth_();
            std::construct_at(data_ + size_, std::in_place_type<T>, std::forward<Args>(args)...);
            ++size_;
            return data_[size_ - 1];
        }

        /**
         * @brief Pop the top element (destroy). / 弹出顶部元素(析构)
         */
        void pop()
        {
            if (empty())
                throw std::out_of_range("stack is empty");
            std::destroy_at(data_ + (size_ - 1));
            --size_;
        }

        /* ------------- allocator / 分配器 ------------- */

        /// @brief get allocator / 获取分配器
        allocator_type get_allocator() const noexcept { return alloc_; }

        /**
         * @brief Rebind to another allocator type. / 迁移到另一种分配器策略
         * @note Copy/move variant elements as needed. / 根据异常安全选择拷贝或移动
         */
        template <class NewAlloc>
            requires RebindableAllocator<NewAlloc, storage_type>
        basic_stack<NewAlloc, SBO, Types...> rebind_allocator(const NewAlloc &na = NewAlloc{}) const
        {
            basic_stack<NewAlloc, SBO, Types...> dst(na);
            dst.reserve(size_);
            for (size_type i = 0; i < size_; ++i)
            {
                dst.push(data_[i]);
            }
            return dst;
        }

    private:
        /* ------------- internal helpers / 内部工具 ------------- */

        // —— SBO helpers / SBO 辅助 —— //
        pointer inline_ptr_() noexcept
        {
            if constexpr (has_sbo)
            {
                // std::launder: 避免潜在的严格别名与生命周期问题
                return std::launder(reinterpret_cast<pointer>(sbo_.buf.data()));
            }
            else
            {
                return nullptr;
            }
        }
        const_pointer inline_ptr_() const noexcept
        {
            if constexpr (has_sbo)
            {
                return std::launder(reinterpret_cast<const_pointer>(sbo_.buf.data()));
            }
            else
            {
                return nullptr;
            }
        }
        bool using_heap_() const noexcept
        {
            if constexpr (has_sbo)
                return data_ != inline_ptr_();
            else
                return data_ != nullptr;
        }
        pointer init_data_ptr_() noexcept
        {
            if constexpr (has_sbo)
                return inline_ptr_();
            else
                return nullptr;
        }
        size_type init_cap_() const noexcept
        {
            if constexpr (has_sbo)
                return SBO;
            else
                return 0;
        }

        static allocator_type rebind_alloc_(const Allocator &a)
        {
            using rebound = typename std::allocator_traits<Allocator>::template rebind_alloc<storage_type>;
            return rebound{a};
        }

        pointer allocate_(size_type n) { return allocator_traits::allocate(alloc_, n); }

        void deallocate_if_heap_() noexcept
        {
            if (using_heap_() and data_)
                allocator_traits::deallocate(alloc_, data_, cap_);
            data_ = init_data_ptr_();
            cap_ = init_cap_();
        }

        static void destroy_n_(pointer p, size_type n) noexcept
        {
            for (size_type i = 0; i < n; ++i)
            {
                std::destroy_at(p + i);
            }
        }

        static void uninit_copy_n_(const_pointer src, size_type n, pointer dst)
        {
            size_type i = 0;
            try
            {
                for (; i < n; ++i)
                    std::construct_at(dst + i, src[i]);
            }
            catch (...)
            {
                destroy_n_(dst, i);
                throw;
            }
        }

        // —— granular move/copy by traits / 基于性质的精细迁移 —— //
        static void uninit_move_or_copy_n_(pointer src, size_type n, pointer dst)
        {
            // Fast path: trivially copyable → memcpy
            if constexpr (triv_copyable)
            {
                std::memcpy(static_cast<void *>(dst), static_cast<void const *>(src), n * TSize);
                return;
            }
            size_type i = 0;
            try
            {
                if constexpr (nothrow_move)
                {
                    for (; i < n; ++i)
                        std::construct_at(dst + i, std::move(src[i]));
                }
                else
                {
                    for (; i < n; ++i)
                        std::construct_at(dst + i, src[i]); // fallback copy
                }
            }
            catch (...)
            {
                destroy_n_(dst, i);
                throw;
            }
        }

        void reallocate_to_(size_type new_cap)
        {
            // 选择目标缓冲区:优先使用 SBO(若可容纳)
            pointer new_buf = nullptr;
            if constexpr (has_sbo)
            {
                new_buf = (new_cap <= SBO) ? inline_ptr_() : allocate_(new_cap);
            }
            else
            {
                new_buf = allocate_(new_cap);
            }

            if (new_buf == data_)
            { // 仍在同一缓冲,无需动作
                cap_ = (new_buf == inline_ptr_()) ? init_cap_() : new_cap;
                return;
            }

            size_type moved = 0;
            try
            {
                uninit_move_or_copy_n_(data_, size_, new_buf);
                moved = size_;
            }
            catch (...)
            {
                if (new_buf != inline_ptr_())
                {
                    destroy_n_(new_buf, moved); // 对于 memcpy 情况,trivial dtor 则无副作用
                    allocator_traits::deallocate(alloc_, new_buf, new_cap);
                }
                throw;
            }
            // 旧缓冲区清理
            destroy_n_(data_, size_);
            if (using_heap_())
                allocator_traits::deallocate(alloc_, data_, cap_);

            data_ = new_buf;
            cap_ = (data_ == inline_ptr_()) ? init_cap_() : new_cap;
        }

        void ensure_growth_()
        {
            if (size_ == cap_)
            {
                const size_type base = (cap_ == 0) ? (has_sbo ? SBO : 0) : cap_;
                const size_type new_cap = (base == 0) ? 4 : (base * 2);
                reallocate_to_(new_cap);
            }
        }

        void assign_move_from_(basic_stack &other)
        {
            clear();
            reserve(other.size_);
            uninit_move_or_copy_n_(other.data_, other.size_, data_);
            size_ = other.size_;
            other.clear();
        }

    private:
        allocator_type alloc_{};
        pointer data_{nullptr};
        size_type size_{0};
        size_type cap_{0};
        // SBO storage (exists only if SBO>0) / 仅当 SBO>0 才有意义
        sbo_storage_t sbo_{};
    };

    /* ========================= Aliases / 别名 ========================= */

    template <class... Types>
    using Stack = basic_stack<std::allocator<std::byte>, 0, Types...>;

    template <std::size_t SBO, class... Types>
    using SmallStack = basic_stack<std::allocator<std::byte>, SBO, Types...>;

    template <class... Types>
    using PmrStack = basic_stack<std::pmr::polymorphic_allocator<std::byte>, 0, Types...>;

    template <std::size_t SBO, class... Types>
    using PmrSmallStack = basic_stack<std::pmr::polymorphic_allocator<std::byte>, SBO, Types...>;

    /* === meta glue: materialize to_basic_stack (after basic_stack exists) === */
    /* !!!修复重定义:只在此处做唯一的偏特化定义,之前仅声明不定义。 */

    namespace detail
    {
        template <class Alloc, class... Ts>
        struct to_basic_stack<Alloc, type_list<Ts...>>
        {
            using type = basic_stack<Alloc, 0, Ts...>;
        };
    } // namespace detail

    /* ========================= Factory helpers / 工厂辅助 ==================== */
    /**
     * @brief Make a stack with deduced unique types from arguments (default allocator).
     *        通过实参类型推导并去重,构造使用默认分配器的栈。
     *
     * @return stack with Types... = unique(remove_cvref_t<Args>...)  / 去重后的类型包
     *
     * 使用示例:
     *   auto s = tools::stack_of(1, std::string{"x"}, 3.14); // Stack<int, std::string, double>
     */
    template <class... Args>
    auto stack_of(Args &&...)
    {
        using uniq_list = typename detail::unique_types<std::remove_cvref_t<Args>...>::type;
        using stack_t = typename detail::to_basic_stack<std::allocator<std::byte>, uniq_list>::type;
        return stack_t{};
    }

    /**
     * @brief Make a stack with a given allocator. / 使用给定分配器的工厂
     */
    template <class Alloc, class... Args>
        requires RebindableAllocator<Alloc, std::variant<std::remove_cvref_t<Args>...>>
    auto stack_of_with_alloc(const Alloc &a, Args &&...)
    {
        using uniq_list = typename detail::unique_types<std::remove_cvref_t<Args>...>::type;
        using stack_t = typename detail::to_basic_stack<Alloc, uniq_list>::type;
        return stack_t{a};
    }

    /**
     * @brief PMR convenience factory. / PMR 快捷工厂
     */
    template <class... Args>
    auto stack_of_pmr(std::pmr::memory_resource *r, Args &&...)
    {
        using uniq_list = typename detail::unique_types<std::remove_cvref_t<Args>...>::type;
        using stack_t = typename detail::to_basic_stack<std::pmr::polymorphic_allocator<std::byte>, uniq_list>::type;
        return stack_t{r};
    }

    /* ========================= CTAD guides / 推导指引 ======================== */
    /**
     * @brief Deduce Ts... from initializer_list<variant<Ts...>> (default allocator).
     *        从 initializer_list<variant<Ts...>> 推导元素类型(默认分配器)
     */
    template <class... Ts>
    basic_stack(std::initializer_list<std::variant<Ts...>>, std::allocator<std::byte>)
        -> basic_stack<std::allocator<std::byte>, 0, Ts...>;
    template <class... Ts>
    basic_stack(std::initializer_list<std::variant<Ts...>>)
        -> basic_stack<std::allocator<std::byte>, 0, Ts...>;

    /**
     * @brief Deduce Ts... + PMR allocator from initializer_list. / 从初始化列表推导 Ts... 与 PMR 分配器
     */
    template <class... Ts>
    basic_stack(std::initializer_list<std::variant<Ts...>>, std::pmr::polymorphic_allocator<std::byte>)
        -> basic_stack<std::pmr::polymorphic_allocator<std::byte>, 0, Ts...>;

} // namespace tools

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2025 azureveil <azureveil4295@yeah.net>
//
// This file is part of azureveil stack demo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include "stack.hpp"

#include <cassert>
#include <string>
#include <iostream>
#include <variant>
#include <vector>
#include <array>
#include <memory_resource>
#include <algorithm>
#include <stdexcept>
#include <cctype>
#include <type_traits>
#include <climits>

// —— 两个测试类型必须放在函数外:标准禁止局部类含静态数据成员 ——

// 计数型:用于验证生命周期(构造/析构数量)
struct Counted
{
    static int live;
    int id = -1;
    Counted() : id(-1) { ++live; }
    explicit Counted(int i) : id(i) { ++live; }
    Counted(const Counted &o) : id(o.id) { ++live; }
    Counted(Counted &&o) noexcept : id(o.id) { ++live; }
    Counted &operator=(const Counted &) = default;
    Counted &operator=(Counted &&) = default;
    ~Counted() { --live; }
};
int Counted::live = 0;

// 用于异常路径:拷贝到第 N 次时抛异常;移动构造非 noexcept,促使“回退拷贝路径”
struct ThrowOnCopy
{
    static int copy_count;
    static int throw_after;
    int v = 0;
    ThrowOnCopy() = default;
    explicit ThrowOnCopy(int x) : v(x) {}
    ThrowOnCopy(const ThrowOnCopy &o) : v(o.v)
    {
        if (++copy_count == throw_after)
            throw std::runtime_error("copy boom");
    }
    ThrowOnCopy(ThrowOnCopy &&o) noexcept(false) : v(o.v) {}
    ThrowOnCopy &operator=(const ThrowOnCopy &) = default;
    ThrowOnCopy &operator=(ThrowOnCopy &&) = default;
    ~ThrowOnCopy() = default;
};
int ThrowOnCopy::copy_count = 0;
int ThrowOnCopy::throw_after = INT_MAX;

int main()
{
    using namespace tools;

    // ========== 1) 基础功能:SmallStack + 多类型 push/emplace/visit ==========
    {
        SmallStack<4, int, std::string, double, Counted> s; // SBO=4
        assert(s.empty());
        s.emplace<int>(42);
        s.push(std::string{"alpha"});
        s.push(3.14);
        s.emplace<Counted>(7);

        assert(s.size() == 4);
        assert(s.capacity() >= 4);
        s.visit_top([](auto const &x)
                    {
            using T = std::decay_t<decltype(x)>;
            if constexpr (std::is_same_v<T, Counted>) assert(x.id == 7); });

        int cnt_int = 0;
        int cnt_str = 0;
        int cnt_dbl = 0;
        int cnt_cnt = 0;
        long long sum_int = 0;
        double sum_dbl = 0.0;
        s.visit_all([&](auto const &x)
                    {
            using T = std::decay_t<decltype(x)>;
            if constexpr (std::is_same_v<T, int>) { ++cnt_int; sum_int += x; }
            else if constexpr (std::is_same_v<T, std::string>) { ++cnt_str; }
            else if constexpr (std::is_same_v<T, double>) { ++cnt_dbl; sum_dbl += x; }
            else if constexpr (std::is_same_v<T, Counted>) { ++cnt_cnt; } });
        assert(cnt_int == 1 and cnt_str == 1 and cnt_dbl == 1 and cnt_cnt == 1);
        assert(sum_int == 42);
        assert(sum_dbl > 3.0 and sum_dbl < 3.2);

        int live_before = Counted::live;
        s.pop(); // 弹出 Counted{7}
        assert(Counted::live == live_before - 1);
        assert(s.size() == 3);
        s.clear();
        assert(s.empty());
    }

    // ========== 2) 容量行为:SBO 命中、溢出堆、shrink 回迁 ==========
    {
        SmallStack<4, int, std::string> s;
        for (int i = 0; i < 4; ++i)
            s.push(i); // SBO 内
        assert(s.capacity() == 4);

        s.push(100); // 触发溢出
        assert(s.capacity() >= 5);

        while (s.size() > 4)
            s.pop(); // 回到 SBO 大小
        s.shrink_to_fit();
        assert(s.capacity() == 4); // 回迁成功
    }

    // ========== 3) reserve/growth:多次重分配不丢数据 ==========
    {
        Stack<int, std::string> s;
        for (int i = 0; i < 100; ++i)
        {
            if (i % 10 == 0)
                s.push(std::string{"s-" + std::to_string(i)});
            else
                s.push(i);
        }
        int ints = 0, strs = 0, sum = 0;
        s.visit_all([&](auto const &x)
                    {
            using T = std::decay_t<decltype(x)>;
            if constexpr (std::is_same_v<T, int>) { ++ints; sum += x; }
            else if constexpr (std::is_same_v<T, std::string>) { ++strs; } });
        assert(ints == 90 and strs == 10);
        assert(s.size() == 100);
        const auto sz = s.size();
        s.shrink_to_fit();
        assert(s.size() == sz);
    }

    // ========== 4) PMR:单调缓冲资源 + PmrSmallStack ==========
    {
        std::array<std::byte, 4096> buf{};
        std::pmr::monotonic_buffer_resource mbr(buf.data(), buf.size());
        PmrSmallStack<4, int, std::string> ps(&mbr);
        ps.emplace<int>(1);
        ps.emplace<std::string>("pmr");
        ps.emplace<int>(2);
        ps.emplace<int>(3); // 填满 SBO
        ps.emplace<int>(4); // 溢出到堆(仍由 mbr 管)
        assert(ps.size() == 5);
        int sum = 0, strings = 0;
        ps.visit_all([&](auto const &x)
                     {
            using T = std::decay_t<decltype(x)>;
            if constexpr (std::is_same_v<T, int>) sum += x;
            else if constexpr (std::is_same_v<T, std::string>) ++strings; });
        assert(sum == (1 + 2 + 3 + 4) and strings == 1);
    }

    // ========== 5) 工厂函数与 CTAD(不再用严格顺序的 static_assert) ==========
    {
        auto s1 = stack_of(1, std::string{"x"}, 2.5, 3, 4.0);
        using stor1 = typename decltype(s1)::storage_type;
        static_assert(std::variant_size_v<stor1> == 3);
        // 运行期验证三种类型都能正常压入/访问
        s1.push(123);
        s1.push(std::string{"ok"});
        s1.push(3.14);
        bool saw_int = false, saw_str = false, saw_dbl = false;
        s1.visit_all([&](auto const &x)
                     {
            using T = std::decay_t<decltype(x)>;
            if constexpr (std::is_same_v<T,int>) saw_int = true;
            if constexpr (std::is_same_v<T,std::string>) saw_str = true;
            if constexpr (std::is_same_v<T,double>) saw_dbl = true; });
        assert(saw_int and saw_str and saw_dbl);

        // PMR 工厂 & initializer_list + CTAD
        std::pmr::monotonic_buffer_resource mbr;
        auto s2 = stack_of_pmr(&mbr, 1, std::string{"y"}, 3.0);
        using stor2 = typename decltype(s2)::storage_type;
        static_assert(std::variant_size_v<stor2> == 3);

        using V = std::variant<int, std::string>;
        basic_stack lst = {V{1}, V{std::string{"ctad"}}}; // Ts... 推导为 <int, std::string>
        assert(lst.size() == 2);
    }

    // ========== 6) rebind_allocator:迁移到 PMR ==========
    {
        auto s = stack_of(1, std::string{"reb"}, 2.0);
        s.push(7);
        s.push(std::string{"z"});
        std::array<std::byte, 2048> buf{};
        std::pmr::monotonic_buffer_resource mbr(buf.data(), buf.size());
        auto sp = s.rebind_allocator(std::pmr::polymorphic_allocator<std::byte>{&mbr});
        assert(sp.size() == s.size());

        auto stringify = [](auto const &v) -> std::string
        {
            return std::visit([](auto const &x) -> std::string
                              {
                using T = std::decay_t<decltype(x)>;
                if constexpr (std::is_same_v<T, std::string>) return x;
                else return std::to_string(x); }, v);
        };

        std::vector<std::string> a, b;
        a.reserve(s.size());
        b.reserve(sp.size());
        for (auto const &e : s)
            a.push_back(stringify(e));
        for (auto const &e : sp)
            b.push_back(stringify(e));
        assert(a == b);
    }

    // ========== 7) 变更访问:就地变换字符串 ==========
    {
        SmallStack<4, int, std::string> s;
        s.push(1);
        s.push(std::string{"MiXed"});
        s.push(2);
        for (auto &v : s)
        {
            std::visit([](auto &x)
                       {
                using T = std::decay_t<decltype(x)>;
                if constexpr (std::is_same_v<T, std::string>) {
                    for (auto& c : x) c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
                } }, v);
        }
        bool seen_upper = false;
        s.visit_all([&](auto const &x)
                    {
            using T = std::decay_t<decltype(x)>;
            if constexpr (std::is_same_v<T, std::string>) seen_upper = (x == "MIXED"); });
        assert(seen_upper);
    }

    // ========== 8) 异常安全(强保证):拷贝途中抛异常,栈保持不变 ==========
    {
        using S = Stack<ThrowOnCopy, int>;
        S s;
        for (int i = 0; i < 8; ++i)
        {
            if (i % 2 == 0)
                s.push(ThrowOnCopy{i});
            else
                s.push(i);
        }
        const std::vector<int> snapshot = [&]
        {
            std::vector<int> vv;
            vv.reserve(s.size());
            for (auto const &e : s)
            {
                std::visit([&](auto const &x)
                           {
                    using T = std::decay_t<decltype(x)>;
                    if constexpr (std::is_same_v<T, int>) vv.push_back(x);
                    else vv.push_back(x.v); }, e);
            }
            return vv;
        }();

        ThrowOnCopy::copy_count = 0;
        ThrowOnCopy::throw_after = 3;

        const auto old_size = s.size();
        const auto old_cap = s.capacity();
        bool threw = false;
        try
        {
            s.reserve(old_cap + 8); // 触发重分配 → 拷贝途中抛异常
        }
        catch (std::runtime_error const &)
        {
            threw = true;
        }
        ThrowOnCopy::throw_after = INT_MAX;

        assert(threw);
        assert(s.size() == old_size); // 强保证:大小不变
        std::vector<int> after;
        after.reserve(s.size());
        for (auto const &e : s)
        {
            std::visit([&](auto const &x)
                       {
                using T = std::decay_t<decltype(x)>;
                if constexpr (std::is_same_v<T, int>) after.push_back(x);
                else after.push_back(x.v); }, e);
        }
        assert(after == snapshot);
    }

    // ========== 9) 生命周期泄漏检查 ==========
    {
        int before = Counted::live;
        {
            SmallStack<4, Counted> s;
            for (int i = 0; i < 16; ++i)
                s.emplace<Counted>(i);
            assert(Counted::live >= before + 16);
            s.clear();
            assert(s.empty());
        }
        assert(Counted::live == before);
    }

    // ========== 10) 顶部访问与异常边界 ==========
    {
        Stack<int> s;
        bool threw = false;
        try
        {
            (void)s.top();
        }
        catch (std::out_of_range const &)
        {
            threw = true;
        }
        assert(threw);
        s.push(7);
        assert(std::get<int>(s.top()) == 7);
        s.pop();
        assert(s.empty());
    }

    std::cout << "[OK] all saturated tests passed.\n";
    return 0;
}