关于C++类模板实例化成员定义的标准规则疑问
首先明确核心结论:显式特化A2<char>::B::func()的操作本身,触发了A2<char>及其中成员类模板B的隐式实例化(包括定义),这是由C++标准中关于类模板实例化时机、显式特化前置要求的规则共同决定的。
关键规则对应(基于n4849)
类模板隐式实例化的触发条件
[temp.inst]第4条:除非类模板特化已被显式实例化或显式特化,否则当该特化被用于需要完整对象类型的上下文,或类类型的完整性影响程序语义时,类模板特化会被隐式实例化。
当你尝试显式特化
A2<char>::B::func()时,编译器需要确认A2<char>::B确实存在成员函数模板func,这就要求A2<char>::B是完整类型(即其定义可见)。而B是A2<char>的成员类模板,要获取B的定义,必须先让A2<char>成为完整类型——因此编译器会触发A2<char>的隐式实例化。类模板成员的实例化规则
[temp.inst]第5条:类模板特化的隐式实例化会触发其成员声明的隐式实例化;成员的定义则会在需要时被隐式实例化。
对于
A2<char>的成员类模板B,因为特化B::func()需要B的定义(以获取func的声明),所以编译器会进一步隐式实例化B的定义,而不仅仅是声明。显式实例化与隐式实例化的区别(解释例1的差异)
[temp.explicit]第1条:如果显式实例化是针对类模板特化,那么该显式实例化会触发类模板特化的成员声明的显式实例化,但不会触发成员模板、成员函数等的定义的显式实例化。
例1中显式实例化
A1<char>时,只会生成成员类模板B的声明,不会生成B的定义。此时尝试特化B::func(),编译器无法获取func的声明(因为B的定义未实例化),因此报错,符合预期。
总结
例2中,显式特化成员函数模板的操作,要求其所属的成员类模板是完整类型,这间接触发了外围类模板特化(A2<char>)及成员类模板(A2<char>::B)的隐式实例化(包括定义),从而让特化操作能够通过编译。
内容的提问来源于stack exchange,提问作者user20575107

