#include <algorithm>
#include <iostream>
#include <new>

using namespace std;

struct A
{
    static void * operator new [] (size_t t, int first, int second);
    static void operator delete [] (void *p, size_t t);
    static void operator delete [] (void *p, int first, int second)
    {
        cout << "3 parameters deallocation: " << first << ", " << second << endl;
        return ::operator delete[](p);
    }
};

// simple POD struct to store the placement parameters
struct info {
	int first_param, second_param;
};

void* A::operator new [] (size_t t, int first, int second)
{
	cout << "3 parameters allocation: " << first << ", " << second << endl;
	// allocate sizeof(info) extra space to store the parameters
    auto const p = ::operator new[](t + sizeof(info));
    auto const pinfo = reinterpret_cast<char*>(p) + t;
    auto const tmp = info{first, second};
    std::copy_n(reinterpret_cast<const char*>(&tmp), sizeof(info), pinfo);
    return p;
}

static void A::operator delete [] (void *p, std::size_t t) {
	// retrieve the parameters that we stored in operator new [].
    auto const pinfo = reinterpret_cast<const char*>(p) + t;
    auto tmp = info{};
    std::copy_n(pinfo, sizeof(info), reinterpret_cast<char*>(&tmp));
    cout << "Deleting with original parameters: " << tmp.first_param << ", " << tmp.second_param << endl;
    ::operator delete[](p);
}

int main()
{
    A *a = new (5,5) A[10]; //operator new [] (size_t, int, int) invoked
    A *b = new (3,7) A[2]; //operator new [] (size_t, int, int) invoked
    delete [] a;
    delete [] b;
}
