为什么即使直到最后才定义实际类型,也可以将依赖名称视为完整
Why can a dependent name be considered as complete even if the actual type is not defined until the very end
考虑这个例子:
template <class T>
void Yeap(T);
int main() {
Yeap(0);
return 0;
}
template <class T>
void YeapImpl();
struct X;
template <class T>
void Yeap(T) {
YeapImpl<X>(); // pass X to another template
}
template <class T>
void YeapImpl() {
T().foo();
}
struct X {
void foo() {}
};
请注意,struct X
直到最后才定义。我曾经认为所有 odr 使用的名称在实例化时都必须是完整的。但是在这里,编译器如何在定义之前将其视为完整类型?
我已经检查了 cppreference 中依赖名称和函数模板实例化的绑定规则和查找规则,但它们都无法解释这里发生了什么。
我相信这个程序格式不正确,不需要诊断。
[temp.point]/8 读取,编辑掉不相关的部分:
函数模板的专用化在翻译单元中可能具有多个实例化点,除了上述实例化点之外,对于在翻译单元内具有实例化点的任何此类专用化,翻译单元的末尾也被视为实例化点。[...]如果两个不同的实例化点根据一个定义规则赋予模板专用化不同的含义,则程序格式不正确,无需诊断。
YeapImpl<X>
有两个实例化点:在问题中的注释行和翻译单元的末尾调用它。在实例化的第一点中,X
是不完整的,这将使函数的主体格式不正确。在实例化的第二点,X
是完整的,这使得身体形成良好。
这两个专业具有[非常]不同的含义。
相关文章:
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 为什么即使调用了析构函数,C++11 中的分离线程也可以执行
- 为什么即使直到最后才定义实际类型,也可以将依赖名称视为完整
- 斯塔克,堆栈,也可以在底部和顶部添加整数
- 重塑Microsoft的并发::d iagnostic::span,也可以检测外部跨度
- 在不工作的情况下为数组分配指针,但反过来也可以
- "fixed"大小的向量在 c++ 中也可以具有假大小(与内存大小相比)吗
- 由于删除对象而导致的 Cpp 代码主线程冻结可以使用智能指针解决,也可以不使用智能指针来解决
- 是库依赖问题可以通过接口避免
- 即使在同一类型上,也可以将击曲线调用新的位置
- 除了两个构造函数外,C++库导入也可以工作
- 张量类,它有自己的存储,但也可以映射外部指针
- 如何将模板类型转换为字符串(如果它也可以是字符串)
- 在C 中的功能可以返回某物,也可以返回任何东西
- 也可以将特征用于1-矢量(标量)
- 在OpenGL 2.1中,即使在2D空间(具有2D纹理),也可以安全使用3D TEX坐标
- 即使在内置素上实例化,也可以向模板参数类型的驱动器进行明确调用
- 仅叮当:一对<路径,路径>可以放入向量中;一对也可以<unique_ptr,unique_ptr>;但不能成对<路径,unique_ptr>:为什么?
- 即使使用 malloc,两个字符 * 也可以具有相同的内存地址吗?