#include <iostream>
#include <memory>
#include <cstdlib>
#include <functional>
#include <new>

bool memory_verbose = false;
void *operator new(std::size_t size)
{
    auto ptr = std::malloc(size);
    if (memory_verbose)
        std::cout << __PRETTY_FUNCTION__ << ":" << size << ":" << ptr << std::endl;
    return ptr;
}

void *operator new(std::size_t size, const std::nothrow_t&)
{
    auto ptr = std::malloc(size);
    if (memory_verbose)
        std::cout << __PRETTY_FUNCTION__ << ":" << size << ":" << ptr << std::endl;
    return ptr;
}
/*
void *operator new[](std::size_t size)
{
    auto ptr = std::malloc(size);
    if (memory_verbose)
        std::cout << __PRETTY_FUNCTION__ << ":" << size << ":" << ptr << std::endl;
    return ptr;
}
void *operator new[](std::size_t size, const std::nothrow_t&)
{
    auto ptr = std::malloc(size);
    if (memory_verbose)
        std::cout << __PRETTY_FUNCTION__ << ":" << size << ":" << ptr << std::endl;
    return ptr;
}
*/
void operator delete(void* ptr) noexcept
{
    if (memory_verbose)
        std::cout << __PRETTY_FUNCTION__ << ":" << ptr << std::endl;
    return std::free(ptr);
}
/*
void operator delete[](void* ptr) noexcept
{
    if (memory_verbose)
        std::cout << __PRETTY_FUNCTION__ << ":" << ptr << std::endl;
    return std::free(ptr);
}
*/

struct FlagGuard
{
public:
    FlagGuard(bool& flag, bool newValue = true) : flagRef(flag), flagBack(flag) { flag = newValue; }
    ~FlagGuard() { flagRef = flagBack; }
private:
    bool& flagRef;
    bool flagBack;
};

int main()
{
    std::cout << sizeof(std::function<void(std::ostream&)>) << std::endl;
    std::cout << sizeof(void(*)(std::ostream&)) << std::endl;
    {
        FlagGuard fg(memory_verbose);
        auto p = new(std::nothrow) char[100];
        delete [] p;
    }
    {
        FlagGuard fg(memory_verbose);
        std::function<void(std::ostream&)> l1 = [](std::ostream& os) { os << "No capture\n"; };
        l1(std::cout);
    }
    {
        FlagGuard fg(memory_verbose);
        int a = 7;
        std::function<void(std::ostream&)> l1 = [a](std::ostream& os) { os << "Capture[a=" << a << "]\n"; };
        std::cout << sizeof(a) << std::endl;
        l1(std::cout);
    }
    {
        FlagGuard fg(memory_verbose);
        struct VLS
        {
             char bs[200] = "Very, very, , very, very, very, very, very, very, very, very, very, very, very, very, very, very, very long string";
        };
        VLS vls;
        std::function<void(std::ostream&)> l1 = [vls](std::ostream& os) { os << "Capture[vls=" << vls.bs << "]\n"; };
        l1(std::cout);
    }
}
