Thread: how can implement a template class like this

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    17

    how can implement a template class like this

    actually, i wanna implement a matrix class. and i also want to enable the member function to initialize the buffer where the data stores.
    i ve considered two means, one is overload function, another is initialization list.
    but it seems not possible for doing that as i hoped
    could anyone provides me a little advice
    thanks alot
    Code:
    template<typename T>
    class Mat{
     public:
    // ....
        Mat();
        ~Mat();
    
    private:
    T ** mem;
    }
    
    
    int main(void)
    {
       Mat a = { {1,2,3}, {2,3,4}};
    // or Mat a({1,2,3},{2,3,4});
     return 0;
    }[

  2. #2
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Read this:
    std::initializer_list - Cppreference

    Get the sizes of the buffers to allocate by caling the size() function of the relevant lists.
    And a for loop, with the iterators to copy.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    17
    Quote Originally Posted by manasij7479 View Post
    Read this:
    std::initializer_list - Cppreference

    Get the sizes of the buffers to allocate by caling the size() function of the relevant lists.
    And a for loop, with the iterators to copy.
    thanks mana,
    that is to say specifing values directly to the buffer is impossible, am i right

  4. #4
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by letmoon View Post
    thanks mana,
    that is to say specifing values directly to the buffer is impossible, am i right
    Not impossible, pass (loaded) pointers directly,
    ..or if you're upto some adventure, learn about move constructors(and use a container to store the data, instead of a T**).

  5. #5
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    It doesn't have anything to do with templates. It doesn't have anything to do with classes.

    You can't ever do that in C++98. That sort of member initialization requires that the members be known.

    The `mem' member variable is known as just being a pointer to a pointer to `T'. You can initialize it as being a point to a pointer to `T'. It isn't known to be an array or anything of the sort so you can't initialize it like one.

    The following code works because you are initializing an array.

    Code:
    struct Test
    {
        unsigned int m[2][2];
    };
    
    int main()
    {
        Test l = {{{0, 1}, {2, 3}}};
        return(0);
    }
    For C++98 your best bet is to avoid the approach. I'd follow the standard set by others and use a range based constructor.

    That said, at cost, you can emulate the behavior through secondary template classes by using the size as a parameter and initializing that object.

    Soma

  6. #6
    Registered User
    Join Date
    Oct 2008
    Posts
    17
    thanks Soma,
    actually, in addtion to this one. i also wanna implement some operator overloads

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    17
    Quote Originally Posted by manasij7479 View Post
    Not impossible, pass (loaded) pointers directly,
    ..or if you're upto some adventure, learn about move constructors(and use a container to store the data, instead of a T**).
    vector, for example
    Code:
    typedef vector<int> i_vec;
    
    // in the class
    // private:
     vector<i_vec> buffer;

  8. #8
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by letmoon View Post
    vector, for example
    How about ,
    Code:
    std::vector<std::vector<T> >
    instead of T** ?
    You don't have to manually maintain any size info, and your assignment will easily work.
    Code:
    Mat(const std::vector<std::vector<T> >& v):mem(v)
    {
    }
    //Disclaimer for phantomotap : C++11 feature used.
    The nested initializer list will be converted to your nested vector implicitly.

    Oh.. and in main, you missed the template parameter : Mat<int>

  9. #9
    Registered User
    Join Date
    Oct 2008
    Posts
    17
    Quote Originally Posted by phantomotap View Post
    It doesn't have anything to do with templates. It doesn't have anything to do with classes.

    You can't ever do that in C++98. That sort of member initialization requires that the members be known.

    The `mem' member variable is known as just being a pointer to a pointer to `T'. You can initialize it as being a point to a pointer to `T'. It isn't known to be an array or anything of the sort so you can't initialize it like one.

    The following code works because you are initializing an array.

    Code:
    struct Test
    {
        unsigned int m[2][2];
    };
    
    int main()
    {
        Test l = {{{0, 1}, {2, 3}}};
        return(0);
    }
    For C++98 your best bet is to avoid the approach. I'd follow the standard set by others and use a range based constructor.

    That said, at cost, you can emulate the behavior through secondary template classes by using the size as a parameter and initializing that object.

    Soma

    Quote Originally Posted by manasij7479 View Post
    How about ,
    Code:
    std::vector<std::vector<T> >
    instead of T** ?
    You don't have to manually maintain any size info, and your assignment will easily work.
    Code:
    Mat(const std::vector<std::vector<T> >& v):mem(v)
    {
    }
    //Disclaimer for phantomotap : C++11 feature used.
    The nested initializer list will be converted to your nested vector implicitly.

    Oh.. and in main, you missed the template parameter : Mat<int>
    thanks u both, really helpful

  10. #10
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    theres multiple problems here. for one, a 2d array is not the same thing as a pointer-to-pointer. also, you cannot implicitly size static arrays of more than one dimension.


    the closest you could come to what you're after is using implicit conversion, like so:

    Code:
    
    template<typename T>
    class Mat{
     public:
        template<unsigned int Rows,unsigned int Columns>Mat(const T(&data)[Rows][Columns]):
    		rows(Rows),
    		columns(Columns),
    		mem(new T[Rows*Columns])
    	{
    		memcpy(mem,data,sizeof(T)*Rows*Columns);
    	}
        ~Mat()
    	{
    		delete[] mem;	
    	}
    	const unsigned int rows;
    	const unsigned int columns;
    	T& operator()(unsigned int row,unsigned int column)
    	{
    		return mem[row*columns+column];
    	}
    	const T& operator()(unsigned int row,unsigned int column)const
    	{
    		return mem[row*columns+column];
    	}
    private:
    T *mem;
    };
     
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int data[][3] =  {{1,2,3}, {2,3,4}};
        Mat<int> a = data;
    	for(unsigned int row = 0; row < a.rows; ++row)
    	{
    		for(unsigned int column=0; column < a.columns; ++column)
    		{
    			std::cout << a(row,column) << '\t';
    		}
    		std::cout << '\n';
    	}
    	std::cin.get();
    }
    i wouldn't recommend doing it this way personally, but here it is.

  11. #11
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    the closest you could come to what you're after is using implicit conversion
    O_o

    Except for the things already discussed (for C++11 and C++98 hacks for a `std::initializer_list' style object).

    Soma

  12. #12
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    838
    i got pulled away and didn't refresh the page before i posted. not familiar with those.

  13. #13
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    *shrug*

    It doesn't matter. Having another option isn't a bad thing.

    Soma

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by m37h0d View Post
    theres multiple problems here. for one, a 2d array is not the same thing as a pointer-to-pointer. also, you cannot implicitly size static arrays of more than one dimension.


    the closest you could come to what you're after is using implicit conversion, like so:

    i wouldn't recommend doing it this way personally, but here it is.
    I would recommend you at least use std::copy instead of memcpy. Otherwise you will get problems with non-primitive types.
    (In fact, don't use memcpy in C++.)
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes, it is a matrix, but it does not need to contain ints or floats or doubles.
    It can contains YourCustomIntegerClass. This is C++, you know... you are using a template class. You cannot be sure of the type T.
    If you use std::copy, it will be correct in all cases. If you use memcpy, you will get silent errors in some cases. Why chase ghosts when a simple line can fix it?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 01-30-2011, 04:28 PM
  2. Replies: 27
    Last Post: 08-21-2008, 11:38 AM
  3. Replies: 9
    Last Post: 11-12-2007, 03:29 PM
  4. Replies: 4
    Last Post: 11-01-2006, 02:23 PM