L
legends2k
Hi,
I've writing a container class as a replacement for raw arrays; just
called it smart_array (bare with me if it's dumb), which has the
niceties of a vector, can be used for dynamic memory requirements and
cleans up itself safely. When I showed it to my friends for a review
and to point out flaws & possible bugs in some peculiar use case; they
said I could post it here to get it reviewed/constructively criticized
by many C++ stalwarts. So am presenting it here:
smart_array.h :
#include <vector>
#include <cassert>
#include <cstdarg>
using std::vector;
template <typename T, size_t N>
class smart_array
{
vector < smart_array<T, N - 1> > vec;
public:
explicit smart_array(vector <size_t> &dimensions)
{
assert(N == dimensions.size());
vector <size_t>::iterator it = ++dimensions.begin();
vector <size_t> dimensions_remaining(it, dimensions.end());
smart_array <T, N - 1> temp_smart_array(dimensions_remaining);
vec.assign(dimensions[0], temp_smart_array);
}
explicit smart_array(size_t dimension_1 = 1, ...)
{
static_assert(N > 0, "Error: smart_array expects 1 or more
dimension(s)");
assert(dimension_1 > 1);
va_list dim_list;
vector <size_t> dimensions_remaining(N - 1);
va_start(dim_list, dimension_1);
for(size_t i = 0; i < N - 1; ++i)
{
size_t dimension_n = va_arg(dim_list, size_t);
assert(dimension_n > 0);
dimensions_remaining = dimension_n;
}
va_end(dim_list);
smart_array <T, N - 1> temp_smart_array(dimensions_remaining);
vec.assign(dimension_1, temp_smart_array);
}
smart_array<T, N - 1>& operator[](size_t index)
{
assert(index < vec.size() && index >= 0);
return vec[index];
}
size_t length() const
{
return vec.size();
}
};
template<typename T>
class smart_array<T, 1>
{
vector <T> vec;
public:
explicit smart_array(vector <size_t> &dimension) :
vec(dimension[0])
{
assert(dimension[0] > 0);
}
explicit smart_array(size_t dimension_1 = 1) : vec(dimension_1)
{
assert(dimension_1 > 0);
}
T& operator[](size_t index)
{
assert(index < vec.size() && index >= 0);
return vec[index];
}
size_t length()
{
return vec.size();
}
};
------ End of smart_array.h ------
Sample Usage:
#include "smart_array.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
// testing 1 dimension
smart_array <int, 1> x(3);
x[0] = 0, x[1] = 1, x[2] = 2;
cout << "x.length(): " << x.length() << endl;
// testing 2 dimensions
smart_array <float, 2> y(2, 3);
y[0][0] = y[0][1] = y[0][2] = 0;
y[1][0] = y[1][1] = y[1][2] = 1;
cout << "y.length(): " << y.length() << endl;
cout << "y[0].length(): " << y[0].length() << endl;
// testing 3 dimensions
smart_array <char, 3> z(2, 4, 5);
cout << "z.length(): " << z.length() << endl;
cout << "z[0].length(): " << z[0].length() << endl;
cout << "z[0][0].length(): " << z[0][0].length() << endl;
z[0][0][4] = 'c'; cout << z[0][0][4] << endl;
// testing 4 dimensions
smart_array <bool, 4> r(2, 3, 4, 5);
cout << "z.length(): " << r.length() << endl;
cout << "z[0].length(): " << r[0].length() << endl;
cout << "z[0][0].length(): " << r[0][0].length() << endl;
cout << "z[0][0][0].length(): " << r[0][0][0].length() << endl;
// testing copy constructor
smart_array <float, 2> copied_y(y);
cout << "copied_y.length(): " << copied_y.length() << endl;
cout << "copied_y[0].length(): " << copied_y[0].length() << endl;
cout << copied_y[0][0] << "\t" << copied_y[1][0] << "\t" <<
copied_y[0][1] << "\t" <<
copied_y[1][1] << "\t" << copied_y[0][2] << "\t" << copied_y[1]
[2] << endl;
return 0;
}
Thanks for your time!
Regards
Sundaram
I've writing a container class as a replacement for raw arrays; just
called it smart_array (bare with me if it's dumb), which has the
niceties of a vector, can be used for dynamic memory requirements and
cleans up itself safely. When I showed it to my friends for a review
and to point out flaws & possible bugs in some peculiar use case; they
said I could post it here to get it reviewed/constructively criticized
by many C++ stalwarts. So am presenting it here:
smart_array.h :
#include <vector>
#include <cassert>
#include <cstdarg>
using std::vector;
template <typename T, size_t N>
class smart_array
{
vector < smart_array<T, N - 1> > vec;
public:
explicit smart_array(vector <size_t> &dimensions)
{
assert(N == dimensions.size());
vector <size_t>::iterator it = ++dimensions.begin();
vector <size_t> dimensions_remaining(it, dimensions.end());
smart_array <T, N - 1> temp_smart_array(dimensions_remaining);
vec.assign(dimensions[0], temp_smart_array);
}
explicit smart_array(size_t dimension_1 = 1, ...)
{
static_assert(N > 0, "Error: smart_array expects 1 or more
dimension(s)");
assert(dimension_1 > 1);
va_list dim_list;
vector <size_t> dimensions_remaining(N - 1);
va_start(dim_list, dimension_1);
for(size_t i = 0; i < N - 1; ++i)
{
size_t dimension_n = va_arg(dim_list, size_t);
assert(dimension_n > 0);
dimensions_remaining = dimension_n;
}
va_end(dim_list);
smart_array <T, N - 1> temp_smart_array(dimensions_remaining);
vec.assign(dimension_1, temp_smart_array);
}
smart_array<T, N - 1>& operator[](size_t index)
{
assert(index < vec.size() && index >= 0);
return vec[index];
}
size_t length() const
{
return vec.size();
}
};
template<typename T>
class smart_array<T, 1>
{
vector <T> vec;
public:
explicit smart_array(vector <size_t> &dimension) :
vec(dimension[0])
{
assert(dimension[0] > 0);
}
explicit smart_array(size_t dimension_1 = 1) : vec(dimension_1)
{
assert(dimension_1 > 0);
}
T& operator[](size_t index)
{
assert(index < vec.size() && index >= 0);
return vec[index];
}
size_t length()
{
return vec.size();
}
};
------ End of smart_array.h ------
Sample Usage:
#include "smart_array.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
// testing 1 dimension
smart_array <int, 1> x(3);
x[0] = 0, x[1] = 1, x[2] = 2;
cout << "x.length(): " << x.length() << endl;
// testing 2 dimensions
smart_array <float, 2> y(2, 3);
y[0][0] = y[0][1] = y[0][2] = 0;
y[1][0] = y[1][1] = y[1][2] = 1;
cout << "y.length(): " << y.length() << endl;
cout << "y[0].length(): " << y[0].length() << endl;
// testing 3 dimensions
smart_array <char, 3> z(2, 4, 5);
cout << "z.length(): " << z.length() << endl;
cout << "z[0].length(): " << z[0].length() << endl;
cout << "z[0][0].length(): " << z[0][0].length() << endl;
z[0][0][4] = 'c'; cout << z[0][0][4] << endl;
// testing 4 dimensions
smart_array <bool, 4> r(2, 3, 4, 5);
cout << "z.length(): " << r.length() << endl;
cout << "z[0].length(): " << r[0].length() << endl;
cout << "z[0][0].length(): " << r[0][0].length() << endl;
cout << "z[0][0][0].length(): " << r[0][0][0].length() << endl;
// testing copy constructor
smart_array <float, 2> copied_y(y);
cout << "copied_y.length(): " << copied_y.length() << endl;
cout << "copied_y[0].length(): " << copied_y[0].length() << endl;
cout << copied_y[0][0] << "\t" << copied_y[1][0] << "\t" <<
copied_y[0][1] << "\t" <<
copied_y[1][1] << "\t" << copied_y[0][2] << "\t" << copied_y[1]
[2] << endl;
return 0;
}
Thanks for your time!
Regards
Sundaram