A question about Template in C++
I know the basics of templates in C++, but I am still learning it. I have a question regarding to the following code:
#include <iostream>
using namespace std;
class PNG {
public:
static void draw() {
cout<<"PNG drawing"<<endl;
}
};
template <typename Image>
void draw() {
Image::draw();
}
int main() {
draw<PNG>();
}
the function draw()
, I pass the type Image
to it, and it will use draw()
method of the Image
.
template <typename Image>
void draw() {
Image::draw();
}
Here, I pass Image
and want to use draw()
method inside of Image
, but template function draw()
has no parameter. So my question is, if I call this template function draw()
in main
in this way: draw<PNG>();
is 开发者_StackOverflowit allowed?
And how the template function draw()
knows the PNG
is a class, and how the class member function draw()
is called?
Your first question
if I call this template function draw() in main in this way: draw(); is it allowed?
As you have realised, the compiler cannot deduce by itself that you mean draw<PNG>
if there are no function arguments from which to figure it out.
So, you have to write (as you already do):
int main() {
draw<PNG>();
}
You cannot omit the template parameter here.
Your second question
and how the template function draw() knows the PNG is a class, and how the class member function draw() is called?
When the function template (A) is instantiated with parameter PNG
, the resulting function body looks like (B):
// A:
template <typename Image>
void draw() {
Image::draw();
}
// B:
PNG::draw();
The parser knows that, for this to work, PNG
must be a namespace or a class/struct. If it's not, the function will not compile.
Say you'd called draw<int>()
instead, for example, your code will try to call int::draw()
, which is not possible.
Now, due to SFINAE (look it up!) you won't get a compilation error for the broken int::draw()
call; this particular instantiation will simply be prohibited from existing. You'll probably be told that there is "no match for function draw()
", as — discounting the prohibited instantiation — there is no possible overload of a function draw
that it can pick to use.
draw<PNG>();
PNG
is passed to the template parameter Image
. So, a corresponding template is instantiated by the compiler. In other words, a function generated with the template parameter Image
being replaced by the call parameter PNG
.
Since PNG::draw()
is a static member function it doesn't require instance to call it. So,
Image::draw(); => PNG::draw() ; // Template parameter substituted and the call
// is made.
You cannot simply call draw()
in your main function like this:
draw();
You either need to use it as the template function or the member function.
PNG dummy;
dummy.draw(); // Okay.
dummy::draw(); // Okay.
draw<PNG>(); // Okay.
draw(); // Not okay.
I'm not sure what you mean by your second question. The typename
keyword, in this case, signifies that the function will accept an object of an unknown type that happens to have a draw()
member.
精彩评论