重复带默认模板参数的类模板前向声明为何报错?
类模板重复声明的默认参数编译规则解析
问题现象
重复声明带有默认模板参数的类模板时会触发编译错误,错误信息如下:
<source>:12:23: error: redefinition of default argument for 'class<template-parameter-1-2>' 12 | template <typename T, typename = T> | ^~~~~~~~ <source>:9:23: note: original definition appeared here 9 | template <typename T, typename = T> |
但无默认模板参数的类模板重复前向声明不会报错,甚至第一次声明带默认参数、第二次声明去掉默认参数的情况也能正常编译。完整示例代码:
// 无默认参数,重复声明合法 template <typename T> struct ok; template <typename T> struct ok; // 带相同默认参数,重复声明报错 template <typename T, typename = T> struct not_ok; template <typename T, typename = T> struct not_ok; // 第一次带默认参数,第二次去掉,编译通过 template <typename T, typename = T> struct why_is_it_ok; template <typename T, typename> struct why_is_it_ok;
原因解析
- 无默认参数的重复声明合法:C++标准允许对类模板进行多次前向声明,只要模板参数列表的结构(参数数量、占位符类型)一致,重复声明就符合规则,这和普通类的重复前向声明逻辑一致。
- 重复指定相同默认参数报错:模板参数的默认参数只能在第一次声明(或定义)时指定,后续声明中不能重复给出——哪怕默认参数的内容完全相同也不行。编译器会将这种重复指定视为“默认参数重定义”,因为默认参数属于模板声明的一部分,重复书写相当于试图修改已确定的默认设置。
- 省略默认参数的二次声明合法:当第一次声明已经指定了默认参数,后续声明省略默认参数时,编译器会认为你是在沿用之前已经确定的默认参数,而非重新定义。此时两次声明的模板参数列表本质兼容——第二个参数依然存在,只是未重复书写默认值,因此不会触发错误。
内容的提问来源于stack exchange,提问作者Sergey Kolesnik
相关产品推荐
相关产品推荐

