2

Here's the code. Is it possible to make last line work?

#include<iostream>
using namespace std;

template <int X, int Y>
class Matrix
{
    int matrix[X][Y];
    int x,y;
    public:
    Matrix() : x(X), y(Y) {}
    void print() { cout << "x: " << x << " y: " << y << endl; }
};

template < int a, int b, int c>
Matrix<a,c> Multiply (Matrix<a,b>, Matrix<b,c>)
{
    Matrix<a,c> tmp;
    return tmp;
}

int main()
{
    Matrix<2,3> One;
    One.print();
    Matrix<3,5> Two;
    (Multiply(One,Two)).print();    // this works perfect
    Matrix Three=Multiply(One,Two); // !! THIS DOESNT WORK
    return 0;
}
gogiel
  • 175
  • 4

4 Answers4

3

In C++11 you can use auto to do that:

auto Three=Multiply(One,Two);

In current C++ you cannot do this.

One way to avoid having to spell out the type's name is to move the code dealing with Three into a function template:

template< int a, int b >
void do_something_with_it(const Matrix<a,b>& One, const Matrix<a,b>& Two)
{
  Matrix<a,b> Three = Multiply(One,Two);
  // ...
}

int main()
{
    Matrix<2,3> One;
    One.print();
    Matrix<3,5> Two;
    do_something_with_it(One,Two);
    return 0;
}

Edit: A few more notes to your code.

  1. Be careful with using namespace std;, it can lead to very nasty surprises.
  2. Unless you plan to have matrices with negative dimensions, using unsigned int or, even more appropriate, std::size_t would be better for the template arguments.
  3. You shouldn't pass matrices per copy. Pass per const reference instead.
  4. Multiply() could be spelled operator*, which would allow Matrix<2,3> Three = One * Two;
  5. print should probably take the stream to print to as std::ostream&. And I'd prefer it to be a free function instead of a member function. I would contemplate overloading operator<< instead of naming it print.
Community
  • 1
  • 1
sbi
  • 219,715
  • 46
  • 258
  • 445
  • I agree with all your code review notes. Be aware that 1 is controversial. Herb Sutter is known to prefer that style. I see his reasoning. He thinks it only ok for `using namespace std;` all others are prohibited. That said, a global `using` in a header is always a bad idea. Again I agree with 1. – deft_code May 25 '10 at 14:47
  • 1
    BTW, C++0x may not be finalized until 2012, so C++11 is just as misleading as C++0x. I prefer C++0x as it is better known and no one expects it to be released in 2009. – deft_code May 25 '10 at 14:52
  • @Caspin: This isn't a header (there's a `main()` function implemented), but still. If Sutter indeed says `using namespace std;` is fine, he is not alone, basically all introductionary C++ books and tutorials use it - which I find very sad. It leads to the kind of subtle bugs as in the question I linked to. [I just ranted about this extensively the other day.](http://stackoverflow.com/questions/2879555/2880136#2880136) – sbi May 25 '10 at 14:57
  • 1
    @Caspin: Every deadline given so far was exceeded. (And I never really bought the hexadecimal argument.) We may need to coin it __Standard C++ 2.0__ then. – sbi May 25 '10 at 14:59
2

This wont be possible in C++03 but C++0x offers auto.

auto Three=Multiply(One,Two);
pmr
  • 58,701
  • 10
  • 113
  • 156
1

No, when using a class template, you have to specify all template arguments explicitly.

If your compiler supports it, you can use auto from C++0x instead:

auto Three=Multiply(One,Two);

In g++, you can enable C++0x support using the -std=c++0x flag.

Thomas
  • 174,939
  • 50
  • 355
  • 478
0

Templates are used at compilation time and are used to implement static polymorphism. This means you should know everything about your objects at the moment your code is being compiled.

Hence, here the compiler fails, because this would be too hard for it to know that Three should have (2,5) dimensions (at least at currently common standard).

If this is a question for "just-to-know", then OK, but in real code you should obviously use constructors to initialize matrix (and set it's dimensions).

M. Williams
  • 4,945
  • 2
  • 26
  • 27