In the "Partial Specializations" section of chapter 14 of C Primer Plus:
Without the partial specialization, the second declaration would use the general template, interpreting T as type char *.With the partial specialization, it uses the specialized template, interpreting T as char.
The partial specialization feature allows for making a variety of restrictions. For example, you can use the following:// general template
template <class T1, class T2, class T3> class Trio{...};// specialization with T3 set to T2
template <class T1, class T2> class Trio<T1, T2, T2> {...};// specialization with T3 and T2 set to T1*
template class Trio<T1, T1*, T1*> {...};Given these declarations, the compiler would make the following choices:
Trio<int, short, char *> t1; // use general template
Trio<int, short> t2; // use Trio<T1, T2, T2>
Trio<char, char *, char *> t3; // use Trio<T1, T1*, T1*>
But when I try this:
template <typename T1, typename T2, typename T3>
class Base
{
public:
Base()
{
cout << "general definition" << endl;
}
};
template <typename T1, typename T2>
class Base<T1, T2, T2>
{
public:
Base()
{
cout << "T1 and T2 definition" << endl;
}
};
template <typename T1>
class Base<T1, T1, T1>
{
public:
Base()
{
cout << "T1 definition" << endl;
}
};
int main()
{
Base<int, char, double> b1;
Base<int, char, char> b2;
Base<int, char> b3;
Base<int, int, int> b4;
Base<int> b5;
return 0;
}
I get errors in Base<int, char> b3
and Base<int> b5
:
wrong number of template arguments (2, should be 3)
wrong number of template arguments (1, should be 3)
My question is: When we use partial specializations, if we use a type parameter to initialize another, can we omitting the repetitive part?
My compiler parameters:
D:\MinGw-x64\mingw64\bin\g .exe 'c:\Users\33065\Desktop\study\C Primer Plus source code\*.cpp', '-o', 'c:\Users\33065\Desktop\study\C Primer Plus source code/main.exe', '-std=c 11', '-g', '-m64', '-Wall', '-static-libgcc', '-fexec-charset=GBK', '-D__USE_MINGW_ANSI_STDIO'
CodePudding user response:
A partial specialization will expect as many template arguments as the base template mandates ("base" meaning the unspecialized declaration of your class template, NOT the type named Base
). A solution to your problem would be to define the base template as:
template <typename T1, typename T2 = T1, typename T3 = T2>
class Base
{
public:
Base()
{
cout << "general defination" << endl;
}
};
Since specializations can't have defaulted template arguments, this makes the base template trickle down non-defined parameters to the rest of the typelist. Hence you can write things like:
Base<T1> b1; // this will be Base<T1, T1, T1>
and have each undefined type equate to the previous type.