两阶段编译检查
在实例化模板的时候,如果模板的参数类型不支持模板中用到的操作符,将会遇到编译期错误,例:
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++是如此的自由、无拘无束,必然是有办法解决这个问题,在此篇中我们先不作赘述。文章来源:https://www.toymoban.com/news/detail-463836.html
有些编译器并不会覆盖执行第一阶段中的所有检查。所以如果模板没有被至少实例化一次的话,你可能一直都不会发现代码中的第一阶段错误。文章来源地址https://www.toymoban.com/news/detail-463836.html
到了这里,关于c++模板编程2-函数模板的定义和使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!