开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜