|
-
January 1st, 2009, 11:23 PM
#1
[RESOLVED] template partial specialization
Hello,
I am trying to implement a dense and sparse matrix class using template specialization. The first two class method definitions work (one with no specialization, one with full specialization), but the third definition with partial specialization does not: if the commented region is uncommented, the example fails to compile.
Code:
#include <iostream>
using std::cout;
enum MatrixType{DENSE,SPARSE};
template<class T,MatrixType MT>
struct Matrix{ Matrix(); };
template<class T, MatrixType MT>
Matrix<T,MT>::Matrix<T,MT>(){
cout << "default constructor\n";
}
template<>
Matrix<double,DENSE>::Matrix<double,DENSE>(){
cout << "<double,DENSE> constructor\n";
}
/*
template<class T>
Matrix<T,DENSE>::Matrix<T,DENSE>(){
cout << "<T,DENSE> constructor\n";
}
*/
int main(){
Matrix<double,SPARSE> V1;
Matrix<int,DENSE> V2;
Matrix<double,DENSE> V3;
return 0;
}
One fix is to do full specializations of all needed types, but this requires a lot of code duplication. I suspect that this has to do with Matrix<T,DENSE> not being recognized as a valid class. Any ideas how to efficiently implement this, or something structurally similar?
Last edited by jakevdp; January 1st, 2009 at 11:31 PM.
Reason: added code tag
-
January 1st, 2009, 11:23 PM
#2
Re: template partial specialization
One more thing: I'm compiling with the gnu g++ compiler
-
January 2nd, 2009, 12:05 AM
#3
Re: template partial specialization
Your code doesn't compile on Comeau C++, regardless of whether that code is commented out or not.
Code:
#include <iostream>
using std::cout;
enum MatrixType{DENSE,SPARSE};
template<class T,MatrixType MT>
struct Matrix{ Matrix(); };
template<class T, MatrixType MT>
Matrix<T,MT>::Matrix<T,MT>()
{
cout << "default constructor\n";
}
template<>
Matrix<double,DENSE>::Matrix<double,DENSE>()
{
cout << "<double,DENSE> constructor\n";
}
/*
template<class T>
Matrix<T,DENSE>::Matrix<T,DENSE>(){
cout << "<T,DENSE> constructor\n";
}
*/
int main(){
Matrix<double,SPARSE> V1;
Matrix<int,DENSE> V2;
Matrix<double,DENSE> V3;
return 0;
}
Code:
Thank you for testing your code with Comeau C/C++!
Tell others about http://www.comeaucomputing.com/tryitout !
Your Comeau C/C++ test results are as follows:
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 10: error: overloaded function "Matrix<T, MT>::Matrix" is not a template
Matrix<T,MT>::Matrix<T,MT>()
^
"ComeauTest.c", line 16: error: overloaded function
"Matrix<T, MT>::Matrix [with T=double, MT=DENSE]" is not a template
Matrix<double,DENSE>::Matrix<double,DENSE>()
^
"ComeauTest.c", line 16: error: expected an identifier
Matrix<double,DENSE>::Matrix<double,DENSE>()
^
3 errors detected in the compilation of "ComeauTest.c".
In strict mode, with -tused, Compile failed
What version of g++ are you compiling with? Always give the version of the compiler, as there can be vast differences in g++ between versions.
Regards,
Paul McKenzie
-
January 2nd, 2009, 12:09 AM
#4
Re: template partial specialization
 Originally Posted by Paul McKenzie
What version of g++ are you compiling with?
gcc version 3.4.5 on mingw
-
January 2nd, 2009, 12:14 AM
#5
Re: template partial specialization
 Originally Posted by jakevdp
gcc version 3.4.5 on mingw
Old.
The latest version of g++ is (as far as I remember) 4.x.
Not fixing the part where the code is commented, the following compiles correctly under Comeau:
Code:
#include <iostream>
using std::cout;
enum MatrixType{DENSE,SPARSE};
template<class T,MatrixType MT>
struct Matrix
{
Matrix();
};
template<class T, MatrixType MT>
Matrix<T,MT>::Matrix()
{
cout << "default constructor\n";
}
template<>
Matrix<double,DENSE>::Matrix()
{
cout << "<double,DENSE> constructor\n";
}
int main(){
Matrix<double,SPARSE> V1;
Matrix<int,DENSE> V2;
Matrix<double,DENSE> V3;
return 0;
}
Regards,
Paul McKenzie
-
January 2nd, 2009, 12:26 AM
#6
Re: template partial specialization
 Originally Posted by jakevdp
One fix is to do full specializations of all needed types, but this requires a lot of code duplication.
Do something similar to what you do in a non-template scenario -- factor out the common code, and place the code that is different in a class. Then you pass this "difference" class as one of the template arguments (this is called policy-based programming).
Your generic Matrix code then uses the policy to determine how to do something at certain strategic points in the generic code.
For an example, look how std::string works. The std::string is really a
Code:
basic_char<char, char_traits<char> >
The bolded part of the template is the policy class.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; January 17th, 2009 at 04:18 AM.
-
January 2nd, 2009, 12:32 AM
#7
Re: template partial specialization
So in general, you have a Matrix class, and the policy determines what to do with various types. Then you have no code duplication at all, since you have one generic function, which calls the policy class to do whatever customizations need to be done. You have "n" different policy classes, all custom.
Of course, the policy class has to have the same public interface so that the generic function can "call" the customized code, but what goes in the policy's public interface is up to the policy -- the generic function doesn't care, as all it does is call the function.
This is also called "compile-time polymorphism". Do a google search on policy-based programming, and you should see many articles on this.
Regards,
Paul McKenzie
-
January 2nd, 2009, 12:37 AM
#8
Re: template partial specialization
Okay. I've compiled the following on g++ v4.1.2 :
Code:
#include <iostream>
using std::cout;
enum MatrixType{DENSE,SPARSE};
template<class T,MatrixType MT>
struct Matrix{
Matrix();
};
template<class T, MatrixType MT>
Matrix<T,MT>::Matrix(){
cout << "default constructor\n";
}
template<>
Matrix<double,DENSE>::Matrix(){
cout << "<double,DENSE> constructor\n";
}
template<class T>
Matrix<T,DENSE>::Matrix(){
cout << "<T,DENSE> constructor\n";
}
int main(){
Matrix<double,SPARSE> V1;
Matrix<int,DENSE> V2;
Matrix<double,DENSE> V3;
return 0;
}
The third member definition produces the following errors:
test.cpp:22: error: invalid use of undefined type 'struct Matrix<T, DENSE>'
test.cpp:7: error: declaration of 'struct Matrix<T, DENSE>'
test.cpp:22: error: template definition of non-template 'Matrix<T, DENSE>::Matrix()'
So the partial specialization of Matrix is not being recognized as a valid class. Does anybody have ideas on how to make this partial specialization work?
-
January 2nd, 2009, 12:50 AM
#9
Re: template partial specialization
Thanks Paul - I think you submitted your last post while I was writing mine
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
|