user707549
user707549

Reputation:

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?

Upvotes: 0

Views: 141

Answers (3)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

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.

Upvotes: 4

Maxpm
Maxpm

Reputation: 25572

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.

Upvotes: -1

Mahesh
Mahesh

Reputation: 34625

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.

Upvotes: 3

Related Questions