Thread: Template function declarations

  1. #1
    Registered User
    Join Date
    Dec 2014
    Posts
    143

    Template function declarations

    So I have this code which prints out an array.

    This version does not work:
    Code:
    #include <iostream>
    
    using namespace std;
    
    
    template <size_t X, size_t Y, class T>
    
    
    void func(T (&arr)[X][Y]);
    
    
    int main()
    {
        int A[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
    
    
        func(A);
        return 0;
    }
    
    
    void func(T (&arr)[X][Y])
    {
        cout << X << "x" << Y << endl;
        
        for (int i=0;i<X;i++) {
            cout << endl;
            for (int j=0;j<Y;j++) {
                cout << arr[i][j] << "\t";
            }    
        }
    }
    While this version does:
    Code:
    #include <iostream>
    
    using namespace std;
    
    
    template <size_t X, size_t Y, class T>
    
    
    void func(T (&arr)[X][Y])
    {
        cout << X << "x" << Y << endl;
        
        for (int i=0;i<X;i++) {
            cout << endl;
            for (int j=0;j<Y;j++) {
                cout << arr[i][j] << "\t";
            }    
        }
    }
    
    
    int main()
    {
        int A[3][3] = {{1,0,0},{0,1,0},{0,0,1}};
    
    
        func(A);
        return 0;
    }
    Why does it not allow me to declare the function before its definition and how could I make that function accept only certain data types?
    Last edited by cmajor28; 12-22-2014 at 09:10 PM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Notice that the forward declaration and the definition does not match.

    If you only want certain types, perhaps you should overload instead.

  3. #3
    Registered User
    Join Date
    Dec 2014
    Posts
    143
    Sorry, I had a copy paste error but I think I fixed it. But I have the exact declaration as definition. I fixed the problem though. I had to add the template to the definition and the declaration, but I have no idea why. Could someone explain?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You are, after all, declaring/defining a function template.

  5. #5
    Registered User
    Join Date
    Dec 2014
    Posts
    143
    I just don't see why I have to say the EXACT same thing twice right before the same function but oh well. Also in my function declaration, I want to only use data types. So how would I format "voidfunc(T (&arr)[X][Y]);" to not have the name of variable "arr"?

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Well, why did you not just write the body of the function template instead of repeating the return type, name, etc? Obviously, the reason is that if you did that, the compiler would have no way of telling with function body belonged to which function. But the thing is, the part with the keyword keyword is likewise important, otherwise the compiler cannot tell if your intention was to define the function template, or to overload the function.

    As for your idea of removing the parameter name: leave it there. It provides semantic information to the reader.

  7. #7
    Registered User
    Join Date
    Dec 2014
    Posts
    143
    It seems like you answer all of my questions haha. Thanks. And the only reason I like the function declarations at the top is because I like my main to be at the top. I honestly don't think I can take out the variable name arr because I've tried SOOOO many combinations with no success.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You cannot, but I can, yet I won't

    You probably just made a mistake somewhere.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Dec 2014
    Posts
    143
    So I started writing my matrix class and this is my header file. I haven't started doing operators yet nor have I started on the cpp file. However, I tried compiling this and I got a ton of errors. Now I figured I would have a few errors but I feel like I have done this ALL WRONG. Could you possibly give me some insight?

    Code:
    #include <iostream>
    #include <vector>
    
    
    using namespace std;
    
    
    #ifndef MATRIX_H
    #define MATRIX_H
    
    
    template <size_t M, size_t N, size_t X, size_t Y, class T, class U>
    
    
    class Matrix{
    
    
    public:
        
        /* Constructors */
        Matrix();
            // Default Constructor
        Matrix(T scaler);
            // Scaler Constructor
        Matrix(T (&array)[N]);
            // 1 dimensional array Constructor
        Matrix(T (&array)[M][N]);
            // 2 dimensional array Constructor
        Matrix(vector<T> &array);
            // 1 Dimensional vector Constructor
        Matrix(vector<vector<T>> &array);
            // 2 Dimensional vector Constructor
            
        /* Destructor */
        ~Matrix();
        
        /* Modifiers */
        void clear();
            // Sets the matrix to null state
        void set(T scaler);
            // Sets the matrix to a scaler
        void set(T (&array)[N]);
            // Sets the matrix to a 1 dimensional array
        void set(T (&array)[M][N]);
            // Sets the matrix to a 2 dimensional array
        void set(vector<T> &array);
            // Sets the matrix to a 1 dimensional vector
        void set(vector<vector<T>> &array);
            // Sets the matrix to a 2 dimensional vector
        
        /* Accessors */
        *T array();
            // Returns an array of the matrix
        *vector<T> vector();
            // Returns a vector of the matrix
        unsigned long int dim();
            // Returns the dimensions of the matrix
            
        /* Functions */
        matrix<T> upper();
            // Returns a matrix of the upper triangular matrix
        matrix<T> lower();
            // Returns a matrix of the lower triangular matrix
        matrix<T> eye();
            // Returns a matrix of the identity matrix
        matrix<T> trans();
            // Returns a matrix of the transpose matrix
        matrix<T> inv();
            // Returns a matrix of the inverse matrix
        matrix<T> zeros();
            // Returns a matrix of the zeros matrix
        *T det(const T (&array) = matrix, unsigned long int i = M, unsigned long int j = N);
            // Returns a double of the determinant of a matrix
        double trace();
            // Returns a double of the trace of a matrix
        
        /* Operators */
    
    
    private:
        /* Member Variables */
        unsigned long int size[2];
            // Array of the matrix dimensions
        T matrix[M][N];
            // Array of the matrix elements
    };
    
    
    #endif
    Last edited by cmajor28; 12-23-2014 at 12:33 AM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This is wrong:
    Code:
    #include <iostream>
    #include <vector>
     
     
    using namespace std;
     
     
    #ifndef MATRIX_H
    #define MATRIX_H
    At file scope in a header, you should not have a using directive. You are not using anything specifically from <iostream> here. Furthermore, the header inclusion guards should cover the entire header, e.g.,
    Code:
    #ifndef MATRIX_H
    #define MATRIX_H
    
    #include <vector>
    Next, does your class template really need so many template parameters?
    Code:
    template <size_t M, size_t N, size_t X, size_t Y, class T, class U>
    What is X, Y and U?

    I suggest that you keep your constructors simple for now. Just have the default constructor that creates a MxN zero matrix and a constructor that takes a scalar such that it creates an MxN matrix with all entries set to that scalar. When you are able to get these two to compile and run correctly, then you can work out how to handle other options for construction.

    These two are simple syntax errors:
    Code:
        *T array();
            // Returns an array of the matrix
        *vector<T> vector();
            // Returns a vector of the matrix
    You mixed up the position of the asterisk. I suggest that you ditch them for now. Rather, write a print member function, or better yet, overload operator<< to print to a std::ostream.

    This:
    Code:
    unsigned long int dim();
    should be:
    Code:
    unsigned long int dim() const;
    Now, you have a bunch of member functions:
    Code:
        matrix<T> upper();
            // Returns a matrix of the upper triangular matrix
        matrix<T> lower();
            // Returns a matrix of the lower triangular matrix
        matrix<T> eye();
            // Returns a matrix of the identity matrix
        matrix<T> trans();
            // Returns a matrix of the transpose matrix
        matrix<T> inv();
            // Returns a matrix of the inverse matrix
        matrix<T> zeros();
            // Returns a matrix of the zeros matrix
        *T det(const T (&array) = matrix, unsigned long int i = M, unsigned long int j = N);
            // Returns a double of the determinant of a matrix
        double trace();
            // Returns a double of the trace of a matrix
    Your upper and lower member functions look strange: perhaps they should be testing if the current matrix is upper/lower triangular? If so, they should return bool. Your eye function, arguably better called identity, should not be a non-static member function. It should be a static member function or a non-member function. Likewise your zeros member function should be a non-static member function or a non-member function (and I note that it is redundant in that default construction of a matrix would presumably result in a zero matrix). Your det member function should probably take no arguments and return a single value. All these non-static member functions should be declared const.

    This looks unnecessary since you already have M and N as template parameters:
    Code:
    unsigned long int size[2]; // Array of the matrix dimensions
    If you do want them as members, then you should have member variables named m and n.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by cmajor28 View Post
    And the only reason I like the function declarations at the top is because I like my main to be at the top.
    Create a header file with all of your template function definitions. Include that header. Problem solved.
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  12. #12
    Registered User
    Join Date
    Dec 2014
    Posts
    143
    The upper and lower function do return a matrix, not a bool. In Linear Algebra the upper matrix is the main diagonal and the elements above it while the rest are zeros. And I only used eye because matlab. Finally the det function needs some parameters because its recursive so I made the default values the member variables. I'm still trying to figure out how to make it recursive. Also X Y and U deal with operators. U is the data type of the other matrix and X and Y are its dimensions. But still, THANK YOU!

    Could you also explain how I would use static member functions and/or non-member functions. I want the functions to get an array as an answer and then pass that array into a constructor to create a matrix of the same data type. So basically the inverse of a matrix object is another matrix object.
    Code:
    double det(T** array = array(), unsigned long int i = M, unsigned long int j = N);
    I fixed the determinant function so that it could be recursive and have default params. However, I feel like I shouldn't have to call array() for it to work. What should I do instead?
    Last edited by cmajor28; 12-23-2014 at 05:03 PM.

  13. #13
    Registered User
    Join Date
    Dec 2014
    Posts
    143
    Code:
    double det(T** array = (&(&matrix)), unsigned long int i = M, unsigned long int j = N);
    I also tried that with no success.

  14. #14
    Registered User
    Join Date
    Dec 2014
    Posts
    143
    Sorry it won't let me edit what I post...I meant to say:

    Code:
    double det(T array = (**matrix), unsigned long int i = M, unsigned long int j = N);

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by cmajor28
    The upper and lower function do return a matrix, not a bool. In Linear Algebra the upper matrix is the main diagonal and the elements above it while the rest are zeros.
    I know what are triangular matrices, hence I asked if those functions should return bool, i.e., to return true if the current matrix is an upper (or lower) triangular matrix.

    If they are supposed to return matrices, then it is not clear to me what "returns a matrix of the upper triangular matrix" actually means. For example, are you just going to zero the entries of the current matrix such that you end up with a triangular matrix? Or is this only for triangularisable matrices? Your comment should state this clearly, and if feasible you should choose a more descriptive name than just upper and lower.

    Quote Originally Posted by cmajor28
    And I only used eye because matlab.
    Right. Matlab is weird.

    Quote Originally Posted by cmajor28
    Finally the det function needs some parameters because its recursive so I made the default values the member variables.
    The fact that det is recursive is implementation detail. It should not feature in the interface, hence you should not add parameters just because you want to support a recursive implementation. For example, perhaps it would be possible to use recursion by creating smaller matrices and then calling their own det member functions, with the base case of say, a 2x2 matrix. Or, perhaps you could have a helper function, e.g., a private member function, that has the necessary parameters. Or, perhaps you could use an explicit stack with iteration.

    Quote Originally Posted by cmajor28
    Also X Y and U deal with operators. U is the data type of the other matrix and X and Y are its dimensions.
    You should not have them as the template parameters of the class template. Rather, you might have them as template parameters of a member function template that operates on another matrix.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 09-13-2013, 04:13 PM
  2. Replies: 3
    Last Post: 01-30-2011, 04:28 PM
  3. Specialising a member function with a template template parameter
    By the4thamigo_uk in forum C++ Programming
    Replies: 10
    Last Post: 10-12-2007, 04:37 AM
  4. Function declarations
    By ssharish2005 in forum C Programming
    Replies: 9
    Last Post: 10-09-2007, 07:06 AM
  5. Template class declarations
    By cunnus88 in forum C++ Programming
    Replies: 9
    Last Post: 02-08-2006, 02:54 AM