Dear c++/g++ programmers: the run result on my system, ubuntuLinux10.04(kernel2.6.35-25), gcc4.5.2 is not what book predict source code http://examples.oreilly.com/9780596007614/ 11-28 11-29 11-24 ---------------------------------- #include "matrix.hpp" #include <iostream> using namespace std; int main( ) { matrix<int> m(2,2); m = 0; m[0][0] = 1; m[1][1] = 1; m *= 2; cout << "(" << m[0][0] << "," << m[0][1] << ")" << endl; cout << "(" << m[1][0] << "," << m[1][1] << ")" << endl; } --------------------------------------------------------------- #ifndef MATRIX_HPP #define MATRIX_HPP #include "stride_iter.hpp" // see <link linkend="cplusplusckbk-CHP-11- SECT-12">Recipe 11.12</link> #include <valarray> #include <numeric> #include <algorithm> template<class Value_T> class matrix { public: // public typedefs typedef Value_T value_type; typedef matrix self; typedef value_type* iterator; typedef const value_type* const_iterator; typedef Value_T* row_type; typedef stride_iter<value_type*> col_type; typedef const value_type* const_row_type; typedef stride_iter<const value_type*> const_col_type; // constructors matrix( ) : nrows(0), ncols(0), m( ) { } matrix(int r, int c) : nrows(r), ncols(c), m(r * c) { } matrix(const self& x) : m(x.m), nrows(x.nrows), ncols(x.ncols) { } template<typename T> explicit matrix(const valarray<T>& x) : m(x.size( ) + 1), nrows(x.size( )), ncols(1) { for (int i=0; i<x.size( ); ++i) m[i] = x[i]; } // allow construction from matricies of other types template<typename T> explicit matrix(const matrix<T>& x) : m(x.size( ) + 1), nrows(x.nrows), ncols(x.ncols) { copy(x.begin( ), x.end( ), m.begin( )); } // public functions int rows( ) const { return nrows; } int cols( ) const { return ncols; } int size( ) const { return nrows * ncols; } // element access row_type row_begin(int n) { return &m[n * cols( )]; } row_type row_end(int n) { return row_begin( ) + cols( ); } col_type col_begin(int n) { return col_type(&m[n], cols( )); } col_type col_end(int n) { return col_begin(n) + cols( ); } const_row_type row_begin(int n) const { return &m[n * cols( )]; } const_row_type row_end(int n) const { return row_begin( ) + cols( ); } const_col_type col_begin(int n) const { return col_type(&m[n], cols( )); } const_col_type col_end(int n) const { return col_begin( ) + cols( ); } iterator begin( ) { return &m[0]; } iterator end( ) { return begin( ) + size( ); } const_iterator begin( ) const { return &m[0]; } const_iterator end( ) const { return begin( ) + size( ); } // operators self& operator=(const self& x) { m = x.m; nrows = x.nrows; ncols = x.ncols; return *this; } self& operator=(value_type x) { m = x; return *this; } row_type operator[](int n) { return row_begin(n); } const_row_type operator[](int n) const { return row_begin(n); } self& operator+=(const self& x) { m += x.m; return *this; } self& operator-=(const self& x) { m -= x.m; return *this; } self& operator+=(value_type x) { m += x; return *this; } self& operator-=(value_type x) { m -= x; return *this; } self& operator*=(value_type x) { m *= x; return *this; } self& operator/=(value_type x) { m /= x; return *this; } self& operator%=(value_type x) { m %= x; return *this; } self operator-( ) { return -m; } self operator+( ) { return +m; } self operator!( ) { return !m; } self operator~( ) { return ~m; } // friend operators friend self operator+(const self& x, const self& y) { return self(x) += y; } friend self operator-(const self& x, const self& y) { return self(x) - = y; } friend self operator+(const self& x, value_type y) { return self(x) += y; } friend self operator-(const self& x, value_type y) { return self(x) -= y; } friend self operator*(const self& x, value_type y) { return self(x) *= y; } friend self operator/(const self& x, value_type y) { return self(x) /= y; } friend self operator%(const self& x, value_type y) { return self(x) %= y; } private: mutable valarray<Value_T> m; int nrows; int ncols; }; #endif --------------------------------------------------------------------------------- // example 11-24. stride_iter.hpp #ifndef STRIDE_ITER_HPP #define STRIDE_ITER_HPP #include <iterator> #include <cassert> template<class Iter_T> class stride_iter { public: // public typdefs typedef typename std::iterator_traits<Iter_T>::value_type value_type; typedef typename std::iterator_traits<Iter_T>::reference reference; typedef typename std::iterator_traits<Iter_T>::difference_type difference_type; typedef typename std::iterator_traits<Iter_T>:ointer pointer; typedef std::random_access_iterator_tag iterator_category; typedef stride_iter self; // constructors stride_iter() : m(NULL), step(0) { }; stride_iter(const self& x) : m(x.m), step(x.step) { } stride_iter(Iter_T x, difference_type n) : m(x), step(n) { } // operators self& operator++() { m += step; return *this; } self operator++(int) { self tmp = *this; m += step; return tmp; } self& operator+=(difference_type x) { m += x * step; return *this; } self& operator--() { m -= step; return *this; } self operator--(int) { self tmp = *this; m -= step; return tmp; } self& operator-=(difference_type x) { m -= x * step; return *this; } reference operator[](difference_type n) { return m[n * step]; } reference operator*() { return *m; } // friend operators friend bool operator==(const self& x, const self& y) { assert(x.step == y.step); return x.m == y.m; } friend bool operator!=(const self& x, const self& y) { assert(x.step == y.step); return x.m != y.m; } friend bool operator<(const self& x, const self& y) { assert(x.step == y.step); return x.m < y.m; } friend difference_type operator-(const self& x, const self& y) { assert(x.step == y.step); return (x.m - y.m) / x.step; } friend self operator+(const self& x, difference_type y) { assert(x.step == y.step); return x += y * x.step; } friend self operator+(difference_type x, const self& y) { assert(x.step == y.step); return y += x * x.step; } private: Iter_T m; difference_type step; }; #endif ---------------------------------------------------------------- my result is (1, 1) (1, 1) but book expect (2 0) (0 2) plz help , Eric linuxubuntu fsshl is online now Click to check your reputation for this post Report This Post ------------------------------------------------------------------------------------------------------------------------------------------------------ an incorrect assumption in the example is that the underlying data in std::valarray is a contiguous block of elements, i.e. an actual array. This may or may not be true. It's obviously true for the writer's compiler; however, it promotes poor coding technique. row_begin, etc. should be using a std::slice created from the int provided. Alternatively, using std::vector instead of std::valarray should work with the type of access used because it's guaranteed by the C++ standard to store elements contiguously. While I'm at it, take a look at this line: Code: const_row_type row_begin(int n) const { return &m[n * cols( )]; } This is completely useless since m[n * cols( )] is an rvalue (i.e. it doesn't have a location) because m is const in this case. This means accessing elements from a const matrix should not work; I'd expect a compiler warning and a segfault. That's not the problem here, however.* I find it entertaining that you're still using this book, given this is the third example from it I've corrected. I'd like to see you correct the next one on your own. Kevin Barry PS I actually don't know if this is the solution to the problem; however, I wouldn't expect anything to work correctly in code written like that. PPS In these lines of main: Code: m[0][0] = 1; m[1][1] = 1; change = 1 to = 17 or something unique like that. If you get 17s instead of 1s in your output, my guess is my first point above is the problem, and that you're assigning to some random address that you're accessing again when you print the elements. *I see now that m is mutable, which means const_row_type row_begin(int n) const should work like row_type row_begin(int n); that is, "incorrectly". mutable is almost always a cheap hack, and I'm certain it's used here so row_begin/col_begin don't have to be written properly. ---------------------------------------------------------------------------------------------------------------------------------------- its result is (17, 17) (17, 17) my g++ compiler at beginning remand me to compile matrix.hpp then get a lot error, and generate matrix.hpp.gch, then g++ matrix.cpp, it generate a.out. If I keep matrix.hpp.gch, then I just modify 1 to 17 in matrix.cpp, it can directly generate a.out. But if I remove matrix.hpp.gch, I need to recompile from matrix.hpp. In the compile error of matrix.hpp, I see something similar as what you mentioned. root@eric-laptop:/home/eric/cppcookbook/ch11# g++ matrix.hpp matrix.hpp:29:25: error: ‘valarray’ does not name a type matrix.hpp:29:25: error: ISO C++ forbids declaration of ‘parameter’ with no type matrix.hpp:29:33: error: expected ‘,’ or ‘...’ before ‘<’ token matrix.hpp:89:13: error: ‘valarray’ does not name a type matrix.hpp: In constructor ‘matrix<Value_T>::matrix()’: matrix.hpp:24:34: error: class ‘matrix<Value_T>’ does not have any field named ‘m’ matrix.hpp: In constructor ‘matrix<Value_T>::matrix(int, int)’: matrix.hpp:25:46: error: class ‘matrix<Value_T>’ does not have any field named ‘m’ matrix.hpp: In copy constructor ‘matrix<Value_T>::matrix(const matrix<Value_T>::self&)’: matrix.hpp:26:27: error: class ‘matrix<Value_T>’ does not have any field named ‘m’ ----------------------------------- should I remove const on most of delcaration? Highly appreciate your time/help to modify these example code but not deviate original too much to achieve the goal of regular matrix op as book suggest. Eric----------- --------------------------------------------------------------------------------------------------------------------------------------------------------------- I tried to remove all const in declaration of my matrix.hpp, but ./ a.out still produce (17, 17) (17, 17) is that possible? and how to fix it? Eric