简体   繁体   中英

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 it 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM