// ----------------
// HeapArrays2D.c++
// ----------------

#include <algorithm> // count, fill
#include <cassert>   // assert
#include <cstddef>   // size_t
#include <iostream>  // cout, endl
#include <vector>    // vector

const std::size_t r =  5;
const std::size_t c = 10;
const std::size_t s = r * c;

const int v = 2;

typedef int (*pointer2d) [c];

void f (int p[][c]) {
    assert(sizeof(p) == 4);
    ++p[2][3];
    ++(*((*(p + 2)) + 3));}

void g (pointer2d p) {
    assert(sizeof(p) == 4);
    ++p[2][3];
    ++(*((*(p + 2)) + 3));}

void h (int* p) {
    assert(sizeof(p) == 4);
    ++p[(2 * c) + 3];
    ++*(p + 23);}

void x (int** p) {
    assert(sizeof(p) == 4);
    ++p[2][3];
    ++(*((*(p + 2)) + 3));}

int main () {
    using namespace std;
    cout << "HeapArrays2D.c++" << endl;

    {
    int* const a = new int[s];
    fill(a, a + s, v);
    assert(count(a, a + s, v) == s);                       // warning
    assert(a[(2 * c) + 3] == v);
//  f(a);                                                  // doesn't compile
//  g(a);                                                  // doesn't compile
    h(a);
    assert(a[(2 * c) + 3] == v + 2);
//  x(a);                                                  // doesn't compile
    const pointer2d p = reinterpret_cast<pointer2d>(a);
    assert(&a[(2 * c) + 3] == &p[2][3]);
    f(p);
    assert(p[2][3] == v + 4);
    g(p);
    assert(p[2][3] == v + 6);
//  h(p);                                                  // doesn't compile
//  x(p);                                                  // doesn't compile
    delete [] a;
    }

    {
    int** const a = new int*[r];
    for (size_t i = 0; i != r; ++i) {
        a[i] = new int[c];
        fill(a[i], a[i] + c, v);
        assert(count(a[i], a[i] + c, v) == c);}            // warning
    assert(a[2][3] == v);
//  f(a);                                                  // doesn't compile
//  g(a);                                                  // doesn't compile
//  h(a);                                                  // doesn't compile
    x(a);
    assert(a[2][3] == v + 2);
    for (size_t i = 0; i != r; ++i)
        delete [] a[i];
    delete [] a;
    }

    {
    int** const a = new int*[r];
    a[0] = new int[s];
    for (size_t i = 1; i != r; ++i)
        a[i] = a[i - 1] + c;
    fill(a[0], a[0] + s, v);
    assert(count(a[0], a[0] + s, v) == s);                 // warning
    assert(a[2][3] == v);
    const pointer2d p = reinterpret_cast<pointer2d>(a[0]);
    f(p);
    assert(a[2][3] == v + 2);
    g(p);
    assert(a[2][3] == v + 4);
    h(a[0]);
    assert(a[2][3] == v + 6);
    x(a);
    assert(a[2][3] == v + 8);
    delete [] a[0];
    delete [] a;
    }

    {
    vector< vector<int> > x(r, vector<int>(c, v));
    assert(x.size()    == r);
    assert(x[0].size() == c);
    assert(x[2][3]     == v);
    vector< vector<int> > y(x);
    assert(x.size() == y.size());
    assert( x[2][3] ==  y[2][3]);
    assert(&x[2][3] != &y[2][3]);
    vector< vector<int> > z(2 * r, vector<int>(2 * c, v));
    x = z;
    assert(x.size() == z.size());
    assert( x[2][3] ==  z[2][3]);
    assert(&x[2][3] != &z[2][3]);
    }

    cout << "Done." << endl;
    return 0;}


syntax highlighted by Code2HTML, v. 0.9.1