关于C++模板的问题

A question about Template in C++

本文关键字:问题 C++ 关于      更新时间:2023-10-16

我知道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传递给它,它将使用Image draw()方法。

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

在这里,我传递Image并想在Image中使用draw()方法,但是模板函数draw()没有参数。所以我的问题是,如果我以这种方式调用这个模板函数draw() maindraw<PNG>();允许它?模板函数draw()如何知道PNG是一个类,以及如何调用类成员函数draw()

你的第一个问题

如果我调用这个模板函数 draw(( 主要以这种方式: draw((;是 它允许吗?

正如您已经意识到的,如果没有函数参数可以弄清楚,编译器本身就无法推断出您的意思draw<PNG>

所以,你必须写(就像你已经做的那样(:

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

此处不能省略模板参数。

你的第二个问题

以及模板函数 draw(( 如何 知道 PNG 是一个类,以及如何 类成员函数 draw(( 是 叫?

当函数模板 (A( 使用参数 PNG 实例化时,生成的函数体如下所示 (B(:

// A:
template <typename Image>
void draw() {
    Image::draw();
}
// B:
    PNG::draw();

解析器知道,要使其正常工作,PNG必须是命名空间或类/结构。如果不是,则函数将不会编译。

例如,假设您调用了draw<int>(),您的代码将尝试调用int::draw(),这是不可能的。

现在,由于SFINAE(查找!(,您不会因中断的int::draw()调用而收到编译错误;此特定实例化将被禁止存在。你可能会被告知"没有匹配的函数draw()",因为 - 忽略禁止的实例化 - 它可以选择使用的函数draw不可能重载。

draw<PNG>();

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

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

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

你不能像这样简单地在主函数中调用draw()

draw();

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

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

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