-
June 4th, 2010, 01:57 PM
#1
Strage problem with arrays
I'm writing a general purpose templated library for vector and matrix math. I want to be able to initialise a matrix with a 2D array. A matrix consists of an array of column vectors. A vector can take a pointer to a 1D array of initial values. I've tested that this works. But the similar constructor for the matrix causes a sigsegv. As far as I can see, all the array math is fine. From the stack trace, the value for initArray in Vec<4,float>::Vec is bogus. It should be pointing to the first element of one of the inner arrays of the 2D array passed into Mat<4,4,float>::Mat in main.
Here's a copy of the call stack at the time of the error:
#0 00417483 Math::Vec<4u, float>::Vec(this=0x28fd30, initArray=0x3f800000) (E:/Documents/Prog/mathlib/vec.h:145)
#1 00417292 Math::Mat<4u, 4u, float>::Mat(this=0x28fe90, initArray=0x28fed0) (E:/Documents/Prog/mathlib/mat.h:80)
#2 00401505 main() (E:/Documents/Prog/mathlib/test_main.cpp:16)
And here is the relevent code from those functions:
main
Code:
typedef Math::Mat<4, 4> Mat4;
float mat_init[4][4] = { {1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1} };
Mat4 m1((const float**)mat_init); // Error here
Mat4 m2((const float**)mat_init);
Matrix constructor
Code:
template <unsigned int X, unsigned int Y, typename T>
Mat<X, Y, T>::Mat(const T** initArray) {
for (unsigned int i=0; i<X; ++i)
cols[i] = Vec<Y, T>(initArray[i]);
}
Vector contructor
Code:
template <unsigned int N, typename T>
Vec<N, T>::Vec(const T* initArray) {
for (unsigned int i=0; i<N; ++i)
els[i] = initArray[i];
}
And the interfaces for vectors and matrices
Code:
template <unsigned int N, typename T = float>
class Vec {
public:
Vec(); // Init elements to default value of type T
Vec(const T* initArray); // Init from array of N elements of type T
Vec(const T& initVal); // Init all elements to initVal
Vec(const Vec& copy);
~Vec();
Vec& operator= (const Vec& rhs);
T& operator[] (unsigned int i);
const T& operator[] (unsigned int i) const;
// Cast to any other type of vector (any dimensions, any element type)
template <unsigned int n, typename t>
operator Vec<n, t> () const;
private:
T els[N];
};
Code:
template <unsigned int X, unsigned int Y, typename T = float>
class Mat {
public:
Mat();
Mat(const T** initArray); // Init by array T [X][Y]
Mat(const Vec<Y, T>* initArray); // Init by array of column vectors
Mat(const Mat& copy);
~Mat();
Mat& operator= (const Mat& rhs);
Vec<Y, T>& operator[] (unsigned int);
const Vec<Y, T>& operator[] (unsigned int) const;
private:
// Store elements as X columns of Y elements of T
Vec<Y, T> cols[X];
};
Thanks.
-
June 4th, 2010, 02:16 PM
#2
Re: Strage problem with arrays
Originally Posted by CodeHippie
Mat4 m1((const float**)mat_init); // Error here
Mat4 m2((const float**)mat_init);
You've encountered an unintuitive but perfectly reasonable issue: a "2D array of T" is not the same as a T**. The fact that you needed an explicit cast to make the compile work should have been your first clue on this matter.
Basically, with a 2D array, the memory layout doesn't include any room for pointers. It doesn't need to; the dimensions are known at compile time, so the compiler can convert multi-dimensional accesses into 1D accesses at compile time.
With a T**, though, you've explicitly got to have an array of pointers. It's a different underlying assumption.
I would also point out that there are several good vector/matrix math libraries out there already: Boost.uBLAS, Eigen, MTL, etc.
-
June 4th, 2010, 02:17 PM
#3
Re: Strage problem with arrays
An array of arrays can be converted to a pointer to an array, but a pointer to an array is not a pointer to a pointer. You should cater for this by having a pointer to an array instead of a pointer to a pointer as the parameter.
-
June 4th, 2010, 02:24 PM
#4
Re: Strage problem with arrays
Right, of course! Thanks a lot man.
-
June 4th, 2010, 02:27 PM
#5
Re: Strage problem with arrays
If you really want to get confused, try and figure out why the compiler will refuse to implicitly convert a T** to a const T**.
-
June 4th, 2010, 03:50 PM
#6
Re: Strage problem with arrays
Originally Posted by Lindley
If you really want to get confused, try and figure out why the compiler will refuse to implicitly convert a T** to a const T**.
Or explicitly as a matter of fact.
Is your question related to IO?
Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|