c++模板编程-两阶段编译检查

C++中的模板在编译时经历两阶段检查,首先检查模板定义的语法和不依赖类型参数的部分,然后在实例化时检查依赖类型参数的部分。这种机制导致模板必须在实例化时可用,通常要求将模板定义放在头文件中。未实例化的模板可能隐藏第一阶段的错误,某些编译器可能不会进行全面的第一阶段检查。两阶段查找规则带来的挑战在于需要确保模板定义在使用时可见。
摘要由CSDN通过智能技术生成

两阶段编译检查

在实例化模板的时候,如果模板的参数类型不支持模板中用到的操作符,将会遇到编译期错误,例:

class Test
{
    //...
};

template <class T>
T add(T a, T b)
{
    return a + b;
}

int main()
{
    Test a, b;
    add(a, b);
}

以上例子 add(a, b) 会在编译器报错,但在模板定义的地方并没有出现错误提示,这是因为模板是分两步编译的:

  • 在模板定义阶段,模板的检查并不包含类型参数。包含下面几个方面:
    • 语法检查。比如误用了中文符号,少写了分号等;
    • 使用了未定义的不依赖于模板参数的符号(变量名、类型名,函数名等);
    • 未使用模板参数的静态断言;
  • 在模板实例化阶段,模板会被二次检查,尤其是依赖于类型参数的部分;

两阶段的检查,强调了是否与模板参数相关,往往与模板参数无关,第一阶段报错,与模板参数有关,第二阶段报错。

例:

template <class T>
T add(T a, T b)
{
    undefine(); //未定义,与模板参数无关,第一阶段报错

    undefine(a, b); //未定义,与模板参数有关,二阶段报错

    static_assert(sizeof(int) > 100, "Error!"); //与模板参数无关,一阶段报错

    static_assert(sizeof(T) > 100, "Error!");//与模板参数有关,二阶段报错

    return a + b;
}

也就是说,只要你定义了模板,并使用了错误的语法,无论使用与否,在编译器都会导致错误,而第二阶段的检查,只有你在实例化模板后,才会进行。这种规则被称之为“两阶段查找”,此规则给模板的处理带来了一个问题:模板实例化的时候,编译器需要看到模板完整的定义,这和函数编译和链接分离的思想背道而驰,目前我们所掌握的知识只能将模板都定义在头文件中,这实在令人沮丧,但c++是如此的自由、无拘无束,必然是有办法解决这个问题,在此篇中我们先不作赘述。

有些编译器并不会覆盖执行第一阶段中的所有检查。所以如果模板没有被至少实例化一次的话,你可能一直都不会发现代码中的第一阶段错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为啥不吃肉捏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值