关于C ++模板的问题

时间:2011-06-06 19:33:33

标签: c++ templates

我知道C ++中模板的基础知识,但我仍在学习它。 我对以下代码有疑问:

#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>();
}

函数draw(),我将类型Image传递给它,它将使用draw()的{​​{1}}方法。

Image

在这里,我传递template <typename Image> void draw() { Image::draw(); } 并希望在Image内使用draw()方法,但模板函数Image没有参数。所以我的问题是,如果我以这种方式在draw()中调用此模板函数draw()main是否允许? 模板函数draw<PNG>();如何知道draw()是一个类,以及如何调用类成员函数PNG

3 个答案:

答案 0 :(得分:4)

您的第一个问题

  

如果我调用此模板函数   以这种方式在main中绘制draw():draw();是   它允许吗?

正如您已经意识到的那样,如果没有函数参数可以解决它,编译器本身不能推导你的意思是draw<PNG>

所以,你必须写(你已经做过):

int main() {
   draw<PNG>();
}

您无法在此处省略模板参数。

您的第二个问题

  

以及模板函数如何绘制()   知道PNG是一类,怎么样   类成员函数draw()是   叫?

当使用参数PNG实例化函数模板(A)时,生成的函数体看起来像(B):

// A:

template <typename Image>
void draw() {
    Image::draw();
}

// B:

    PNG::draw();

解析器知道,为了使其工作,PNG必须是命名空间或类/结构。如果不是,则该函数将无法编译。

比如说你打电话给draw<int>(),例如,你的代码会尝试拨打int::draw(),这是不可能的。

现在,由于SFINAE(查找它!),您将不会因损坏的int::draw()电话而收到编译错误;这种特殊的实例化将被禁止存在。你可能会被告知“函数draw()没有匹配”,因为 - 对禁止的实例进行折扣 - 它可以选择使用的函数draw不会超载。

答案 1 :(得分:3)

draw<PNG>();

PNG将传递给模板参数Image。因此,编译器会实例化相应的模板。换句话说,使用模板参数Image生成的函数将被调用参数PNG替换。

由于PNG::draw()是静态成员函数,因此不需要实例来调用它。所以,

Image::draw(); => PNG::draw() ; // Template parameter substituted and the call 
                                // is made.

答案 2 :(得分:-1)

您不能简单地在主函数中调用draw(),如下所示:

draw();

您需要将其用作模板函数或成员函数。

PNG dummy;
dummy.draw(); // Okay.
dummy::draw(); // Okay.
draw<PNG>(); // Okay.
draw(); // Not okay.

我不确定你的第二个问题是什么意思。在这种情况下,typename关键字表示该函数将接受恰好具有draw()成员的未知类型的对象。