对应于模板中的定义的声明
Declaration that corresponds to a definition in a template
N4296::14.7.1/1 [temp.inst]
提供了以下示例:
template<class T, class U>
struct Outer {
template<class X, class Y> struct Inner;
template<class Y> struct Inner<T, Y>; // #1a
template<class Y> struct Inner<T, Y> { }; // #1b; OK: valid redeclaration of #1a
template<class Y> struct Inner<U, Y> { }; // #2
};
Outer<int, int> outer; // error at #2
并给出以下解释:
Outer<int, int>::Inner<int, Y>
在#1b
重新声明。(它不是 已定义,但注明与 中的定义相关联Outer<T, U>
.(#2
也是对#1a
的重新声明。它被指出为 与定义相关联,因此它是相同的无效重新声明 部分专业化。
我对#1b
被视为宣言而不是定义这一事实感到困惑。我们在那里明确提供了函数体,为什么它仍然不是一个定义?事实上,你无法解释这种兴奋吗?
这在示例前面的文本中进行了解释!
类模板专用化的隐式实例化会导致类成员函数、成员类、作用域成员枚举、静态数据成员和成员模板的定义或默认参数的隐式实例化,但不是定义或默认参数的隐式实例化;它会导致无作用域成员枚举和成员匿名联合的定义隐式实例化。但是,为了确定成员的实例化重新声明是否根据 9.2 有效,与模板中的定义对应的声明被视为 定义。
实例化模板产生的函数定义与函数模板本身的定义之间存在差异。
名称通过其第一个声明引入其范围,然后与对象、函数或类等实体相关联。在某些作用域(如命名空间作用域或类作用域(中,可以多次声明名称。名称声明还可以包括命名实体的定义。在看到定义之后,据说有关声明与定义相关联。命名实体不允许使用多个定义。
隐式实例化类模板时,不会立即实例化其嵌套函数、类和静态对象成员的定义。它们仅在需要时立即实例化。但是,有一个特殊的规则可以捕获潜在的定义冲突。
在此示例中,在具有两个参数 T
和 U
的类模板中,声明了具有两个参数 X
和 Y
的内部类模板。为内部类定义了两个部分专用化,一个用于X
与T
重合的情况,另一个用于X
与U
重合的情况。第一个部分专业化首先在 #1a 声明,然后在 #1b 重新声明并与定义相关联。声明第二个部分专用化并与 #2 处的定义相关联。
目前为止,一切都好。
但是,如果T
和U
是同一类型,例如int
呢?在这种情况下,对于任何给定的Y
,#1a、#1b 和 #2 中的声明都声明相同的名称 Outer<int, int>::Inner<int, Y>
。其中两个声明与定义相关,这会导致冲突。您引用的 N4296 中的示例是为了证明即使没有需要实例化Outer<int, int>::Inner<int, Y>
的引用,也必须诊断冲突。
Outer<int, char>
很好,因为在这种情况下,T
和U
不一致,因此 #2 为Outer<int, char>::Inner<char, Y>
提供了与 #1b 中定义的Outer<int, char>::Inner<int, Y>
不同的定义。
- 如何确保C++函数在定义之前声明(如override关键字)
- 为什么在定义函数之前先声明它
- 为什么我不能在一个类的不同行中声明和定义成员变量?
- Visual Studio中的函数声明和函数定义问题
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 如何在标头中声明(或定义)函数的问题
- 程序顶部的声明与定义(最佳实践)
- 类的前向声明之后的类成员函数定义,在类声明之前
- 静态变量声明和定义
- C++ G++ 编译器 - 错误:隐式声明的定义
- C++:错误重定义和先前声明
- 类模板静态数据成员定义/声明/初始化
- 只有一个定义/声明时标头声明变量的多堆定义错误
- OpenCV - Ptr 语法和类定义/声明 - 混淆?
- 如何为非类型模板类的专用化定义声明之外的方法
- 我如何防止静态类成员变量需要两个定义/声明
- 默认定义声明的详细程度不完整
- C++:非成员函数的定义/声明的位置
- 将比较操作符的重载定义/声明为库中的非成员函数
- C++头重新定义/声明混合