为什么const变量不需要在模板类中初始化,直到类被实际使用?
如果我不在const未使用的模板类中初始化变量,为什么编译器不会抛出错误?如果我删除template关键字,编译器会按预期抱怨。
此代码有效(意外):
#include <iostream>
template<class T>
class Matrix {
private:
const uint8_t numRows, numColumns;
T content[];
public:
Matrix(uint8_t numRows, uint8_t numColumns)
// : numRows(numRows), numColumns(numColumns) -- Works fine
{
std::cout << "Matrix" << std::endl;
}
};
int main() {
// If Matrix constructor is not called the compiler doesn't need a initialization list
// Matrix<int> matrix(2, 2);
return 0;
}
但是这个没有(预期):
#include <iostream>
template<class T>
class Matrix {
private:
const uint8_t numRows, numColumns;
T content[];
public:
Matrix(uint8_t numRows, uint8_t numColumns)
// : numRows(numRows), numColumns(numColumns) -- Does NOT work
{
std::cout << "Matrix" << std::endl;
}
};
int main() {
Matrix<int> matrix(2, 2);
return 0;
}
回答
直到需要时才会隐式实例化类模板。您不使用Matrix<int>,则它不会被实例化,并且不需要定义(存在或格式良好)。
当代码在需要完全定义类型的上下文中引用模板时,或者当类型的完整性影响代码时,并且该特定类型尚未显式实例化时,就会发生隐式实例化。例如,当构造此类型的对象时,而不是在构造指向此类型的指针时。
从标准,[temp.inst]/2:
除非类模板特化是声明的特化,否则当在需要完全定义的对象类型的上下文中引用特化或类类型的完整性影响程序的语义时,类模板特化会被隐式实例化。
[temp.inst]/11:
(强调我的)
实现不应隐式实例化函数模板、变量模板、成员模板、非虚拟成员函数、模板化类的成员类或静态数据成员,或 constexpr if 语句的子语句 ([stmt.if ]),除非需要这样的实例化。
因此,在这种情况下,Matrix<T>::Matrix(uint8_t numRows, uint8_t numColumns)不允许隐式实例化格式错误。
- @HolyBlackCat There might be specialization as `Matrix<int>` which is well-formed. We can't judge that the code is ill-formed just because the primary template is. https://wandbox.org/permlink/LJKpqqQjIn4UoBCZ