M
Mike Wahler
Thanks again for your explanation.template < typename T >
class Matrix {
void check_limits( unsigned h, unsigned v ) const {
if ( h >= h_limit || v >= v_limit )
throw std:ut_of_range( "Matrix" );
}
std::deque<T> buffer;
unsigned h_limit, v_limit;
public:
Matrix():
h_limit( 0 ),
v_limit( 0 ) { }
Matrix( unsigned h, unsigned v ):
buffer( h * v ),
h_limit( h ),
v_limit( v ) { }
T& cell_at( unsigned h, unsigned v ) {
check_limits();
return buffer[ h_limit * h + v ];
}
const T& cell_at( unsigned h, unsigned v ) const {
check_limits();
return buffer[ h_limit * h + v ];
}
};
use it like this:
Matrix<float> m( 100, 100 )
assert( m.cell_at( 12, 5 ) == 0 );
m.cell_at( 12, 5 ) = 9;
assert( m.cell_at( 12, 5 ) == 9 );
Which method(s) are you having trouble understanding?
check_limits(unsigned h, unsigned v): checks to make sure that h & v
represent a cell in the Matrix.
Matrix(): creates an empty (0 x 0) matrix.
Matrix(unsigned h, unsigned v): creates and initializes all the elements
in an h x v matrix.
cell_at(unsigned h, unsigned v): returns a modifiable reference to a
cell in the matrix.
cell_at(unsigned h, unsigned v) const: returns an unmodifiable reference
to a cell in the matrix.
The matrix is actually held in an array (a deque in this case, but it
could as easily be held in a vector.) Something like this:
00 10 20
01 11 21
02 12 22
is held in the array like this:
00 10 20 01 11 21 02 12 22
I'm having trouble understanding:
Where does the function "cell_at" come from.
It came from Daniel, he wrote it. I suspect he used
the name 'cell_at' to mimic the name of a similar
member function from the standard class 'std::vector'.
The vector class has a subscript operator ( [] ) that
works just like with an array, but also like an array
is not bounds checked. It also has a element-access
function which does do bounds checking, called 'at()'.
So he came up with 'cell_at()' for the name.
I'm not to familiar with the use of "std::deque<T> buffer;"
'std::queue' is one of several 'container' classes provided
by the C++ standard library. It's a templated class (as
are all the containers), with the template parameter 'T'
specifying the actual type of the elements stored in it.
e.g.
where are some good
examples?
I don't know of any online, but a good textbook should have some.
The most recommended book on the standard library is:
www.josuttis.com/libbook I *highly* recommend it.
I checked the help section of vc++6.0 but the deque examples were not
the same.
Why do h and v have to be unsigned?
They don't *have* to be, but it makes sense for them to be.
A signed type would allow for negative values (and only has
half the value range of the corresponding unsigned type).
But what would a negative size or index *mean*? Also note that
'h' and 'v' shouldn't really be just any unsigned type, but type
'size_t', which is an (implementation-defined) unsigned type which
is guaranteed to be able to hold the largest possible sized object
(or the largest number of one-byte objects). Actually it should
have the same type as the container class ('deque' in this case)'s
'size_type' type. But I suppose allowing for that would make the
code even harder for you to follow.
Why is the "const {" there in
"void check_limits( unsigned h, unsigned v ) const{"
const T& cell_at( unsigned h, unsigned v ) const {
Look up 'const member function'. The 'const' after the
parameter list is a 'promise' to the compiler that the
function will not modify the object for which it was called.
If you write code that tries to do so, you'll get a compile
error.
If the class is defined outside the function
The class is defined outside any function (as it should be).
is "buffer" static when the
function is exited?
What function? Anyway, an object will have static storage duration
in two cases:
1. It's defined at file scope (outside any function or class)
2. It's specifically qualified with the 'static' keyword.
-Mike