Jump to content
  • Advertisement
Sign in to follow this  
ermitgilsukaru

Trouble with template classes (C++)

This topic is 4482 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi. I'm new here. Hope it's not to presumptive of me to plead for help in my first post, and not in the newb-section either. I'm trying to convert my math-classes into templates and am having some troubles. I have a Matrix4x4 class with column-major data (because OpenGL wants it like that). But I prefer to view the matrix as row-major. Therefore I made an inner class, MatrixRow, to enable the C-style M[row][column] indexing. This all works fine when the code isn't templated, but I can't get it to compile when I convert it to a template. On to the code:
/// The homogenous coordinate transformation matrix. The matrix elements can be
/// accessed in C style M[row][column].
template <typename real>
class Matrix4x4 {
    public:
        // --------------- Data ------------------- //
        real m[16];
        // ---------------------------------------- //

        /// Helper-class for Matrix4x4 that makes the Matrix4x4 look like
        /// a row major array from the outside, instead of the actual column
        /// major layout that OpenGL needs.
        class MatrixRow {
            friend class Matrix4x4<real>;
            public:
                real& operator[] (int j);

            private:
                real* rowBase;
                MatrixRow() {} // Should not be created by anything besides the
                               // Matrix4x4 class.
            };


        MatrixRow operator[] (int i);
};


template <typename real>
inline real& Matrix4x4<real>::MatrixRow::operator[] (int j) {
    assert(j < 4);
    
    return *(rowBase + (j * 4));
}

template <typename real>
inline Matrix4x4<real>::MatrixRow Matrix4x4<real>::operator[] (int i) {
    assert(i < 4);

    MatrixRow row;
    row.rowBase = m + i;
    
    return row;
}
The class is heavily edited. I'm only showing the relevant code. I'd really appreciate if somebody could tell me what's wrong with this code. Also, feel free to rip on my design decisions. I'm new at this and, truth be told, I suck.

Share this post


Link to post
Share on other sites
Advertisement
As was said, please post the error. One thing I notice is you don't have any const accessors shown. Also:


inline typename Matrix4x4<real>::MatrixRow Matrix4x4<real>::operator[]

Share this post


Link to post
Share on other sites
I got the error error: expected initializer before 'Matrix4x4' on GCC4.0, Mac OS 10.4.7

"Matrix4x4<real>::MatrixRow" is the returntype in the declaration, so no need for typename.

I've declared a const accessor in the real class, but I didn't think it was neccessary to show it here. It's just duplicate code with a few strategally placed consts.

Anyway, thanks for at least taking the time to look at my problem.

Oh, also, how do I qoute a post on this board? The BB-tags ([QOUTE][/QOUTE]) don't seem to work.

Share this post


Link to post
Share on other sites
Quote:
Original post by ermitgilsukaru
"Matrix4x4<real>::MatrixRow" is the returntype in the declaration, so no need for typename.

Yes, you do need the typename keyword to disambiguate the grammer so that C++ knows to treat Matrix4x4<real>::MatrixRow as a nested type, not a member variable:
Quote:
GCC 3.4.2
matrix_error.cpp:37: warning: `Matrix4x4<real>::MatrixRow' is implicitly a typename
matrix_error.cpp:37: warning: implicit typename is deprecated, please see the documentation for details
Quote:
Visual C++ 8.0
matrix_error.cpp(37) : warning C4346: 'Matrix4x4<real>::MatrixRow' : dependent name is not a type
prefix with 'typename' to indicate a type

If that doesn't fix the problem (and I expect it will), can you tell us which line the error message indicates.

Σnigma

Share this post


Link to post
Share on other sites


/// The homogenous coordinate transformation matrix. The matrix elements can be
/// accessed in C style M[row][column].
template <typename real>
class Matrix4x4 {
public:
// --------------- Data ------------------- //
real m[16];
// ---------------------------------------- //

/// Helper-class for Matrix4x4 that makes the Matrix4x4 look like
/// a row major array from the outside, instead of the actual column
/// major layout that OpenGL needs.
class MatrixRow {
friend class Matrix4x4<real>;
public:
real& operator[] (int j);

private:
real* rowBase;
MatrixRow() {} // Should not be created by anything besides the
// Matrix4x4 class.
};


MatrixRow operator[] (int i);
};


template <typename real>
inline real& Matrix4x4<real>::MatrixRow::operator[] (int j) {
// assert(j < 4);

return *(rowBase + (j * 4));
}

template <typename real>
inline class Matrix4x4<real>::MatrixRow Matrix4x4<real>::operator[] (int i) {
// assert(i < 4);

MatrixRow row;
row.rowBase = m + i;

return row;
}





that compiles without error ...
I added class int the last function deklaration.

Share this post


Link to post
Share on other sites
Quote:
Original post by dragongame
*** Source Snippet Removed ***

that compiles without error ...
I added class int the last function deklaration.


Gcc can grok it, but it's not standard C++ and Visual C++ chokes:
Quote:
Visual C++ 8.0
matrix_error.cpp(44) : fatal error C1001: An internal error has occurred in the
compiler.

The correct solution, as already posted, is to use typename.

Σnigma

Share this post


Link to post
Share on other sites
Quote:
Original post by ermitgilsukaru
I got the error error: expected initializer before 'Matrix4x4' on GCC4.0, Mac OS 10.4.7


Don't make us play 20 questions guessing the line this occurs on please.

Quote:
"Matrix4x4<real>::MatrixRow" is the returntype in the declaration, so no need for typename.


You misunderstand when this keyword is needed. Because Matrix4x4< real > depends on the template parameter real, Matrix4x4< real >::MatrixRow becomes a dependant name. Since in this case it's a type, it becomes a dependant typename, which requires the use of this keyword. Try compiling this example in your compiler with and without the typename keyword yourself if you still don't believe me. VS2k5 will not compile it without the typename keyword.

template < typename T >
class foo {
public:
class bar {};

bar func();
};

template < typename T >
typename foo< T >::bar foo< T >::func() { return bar(); }

int main () {
}




Quote:
Oh, also, how do I qoute quote a post on this board? The BB-tags ([QOUTE][/QOUTE]) don't seem to work.


Fixed. 'nuff said.

Share this post


Link to post
Share on other sites
Damn, I feel braindead. First with the spelling mistakes (quote and strategically), and second I misunderstood what Polymorphic OOP meant by the typename comment. I thought he was trying to tell me that the return type was missing.

My bad, on both counts.

I'm not at my computer right now, so I can't try the fix you all suggested.

Lastly, I wasn't being recalcitrant (imagine that, I can spell recalcitrant correctly, but not quote) with the compiler error messages; there were no line numbers in the error message.

I will post again when I'm at my computer.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!