#include <string>
#include <vector>
#include <iostream>
#include <iomanip>
#include <utility>
#include <memory>
#include <cassert>
#include <atomic>
#include "sharedptr.h"
using namespace std;

int main() {
    // 1. make_shared<T>() combines heap allocations
    {
        // string*            p0 { new string(50, 'A') };
        // shared_ptr<string> p1 { new string(50, 'B') };
        // shared_ptr<string> p2 { make_shared<string>(50, 'C') };
    }

    // 2. shared_ptr to an array and custom deleter
    {
        // Invalid delete
        // SharedPtr<string> p0 { new string[2] {"hello", "c2cpp"} };
        // cout << *p0 << ' ' << p0.get_ptr()[1] << '\n';

        // Invalid delete
        // shared_ptr<string> p1 { new string[2] {"hello", "c2cpp"} };
        // cout << *p1 << ' ' << p1.get()[1] << '\n';

        // Custom deleter
        // shared_ptr<string> p2 { new string[2] {"hello", "c2cpp"},
        //     [](string* s) { delete[] s; }
        // };
        // cout << *p2 << ' ' << p2.get()[1] << '\n';

        // shared_ptr parameterized with array type
        // shared_ptr<string[]> p3 { new string[2] {"hello", "c2cpp"} };
        // cout << p3[0] << " " << p3[1] << '\n';
    }

    // 3. Aliasing
    {
    //     shared_ptr<pair<string,int>> p1 { new pair{"hi"s, 5} };
    //     shared_ptr<int>              p2 { p1, &p1->second };

    //     cout << p1->first << ' ' << *p2 << '\n';

    //     assert(p1.use_count() == 2 && p2.use_count() == 2);
    }

    // 4. weak_ptr
    {
    //     auto weak_test = [](weak_ptr<string> wp) {
    //         shared_ptr<string> sp = wp.lock();
    //         if (sp) {
    //             assert(sp.use_count() == 2);
    //             cout << *sp << '\n';
    //         } else {
    //             cout << "weak_ptr expired\n";
    //         }
    //     };

    //     weak_ptr<string> wp;

    //     {
    //         auto sp = make_shared<string>("hello");
    //         assert(sp.use_count() == 1);

    //         wp = sp;                     // weak_ptr does not increase
    //         assert(sp.use_count() == 1); // the shared_ptr's ref count

    //         weak_test(wp); // sp is alive, so is wp
    //     }

    //     weak_test(wp); // sp is gone, so wp is expired
    }
}
