为什么在实际使用 class 之前,不需要在模板 class 中初始化 const 变量?
Why do const variables don't need to be initialized in a template class until the class is actually used?
如果我没有在未使用的模板 class 中初始化 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;
}
Class template 直到需要时才会隐式实例化。您不使用 Matrix<int>
,那么它不会被实例化,并且不需要定义(存在或格式良好)。
When code refers to a template in context that requires a completely defined type, or when the completeness of the type affects the code, and this particular type has not been explicitly instantiated, implicit instantiation occurs. For example, when an object of this type is constructed, but not when a pointer to this type is constructed.
根据标准,[temp.inst]/2:
Unless a class template specialization is a declared specialization, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
(强调我的)
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
所以在这种情况下,不允许隐式实例化格式错误的Matrix<T>::Matrix(uint8_t numRows, uint8_t numColumns)
。
代码格式错误,无需诊断(意味着代码无效,但不需要编译器检测此事实)。
这是由[temp.res.general]/6.4
造成的:
The program is ill-formed, no diagnostic required, if:
— a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, ...
如果我没有在未使用的模板 class 中初始化 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;
}
Class template 直到需要时才会隐式实例化。您不使用 Matrix<int>
,那么它不会被实例化,并且不需要定义(存在或格式良好)。
When code refers to a template in context that requires a completely defined type, or when the completeness of the type affects the code, and this particular type has not been explicitly instantiated, implicit instantiation occurs. For example, when an object of this type is constructed, but not when a pointer to this type is constructed.
根据标准,[temp.inst]/2:
Unless a class template specialization is a declared specialization, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
(强调我的)
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
所以在这种情况下,不允许隐式实例化格式错误的Matrix<T>::Matrix(uint8_t numRows, uint8_t numColumns)
。
代码格式错误,无需诊断(意味着代码无效,但不需要编译器检测此事实)。
这是由[temp.res.general]/6.4
造成的:
The program is ill-formed, no diagnostic required, if:
— a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, ...