首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >试图理解模板和名称查找

试图理解模板和名称查找
EN

Stack Overflow用户
提问于 2019-12-16 09:16:52
回答 1查看 202关注 0票数 8

我试图理解下面的代码片段

片段#1

代码语言:javascript
复制
template <typename T>
struct A
{
    static constexpr int VB = T::VD;
};

struct B : A<B>
{
};

gcc9和clang9都不会在这里抛出错误。

问:为什么这段代码要编译?我们不是在从B继承时实例化A<B>吗?B中没有VD,所以编译器不应该在这里抛出一个错误吗?

片段#2

代码语言:javascript
复制
template <typename T>
struct A
{
    static constexpr auto AB = T::AD; // <- No member named AD in B
};

struct B : A<B>
{
    static constexpr auto AD = 0xD;
};

在这种情况下,gcc9编译得很好,但是clang9抛出一个错误,上面写着“B中没有名为AD的成员”。

问:为什么它要用gcc9 9编译/为什么不用clang9编译?

片段#3

代码语言:javascript
复制
template <typename T>
struct A
{
    using TB = typename T::TD;
};

struct B : A<B>
{
    using TD = int;
};

这里,clang9和gcc9都会抛出一个错误。gcc9说“不完整类型'struct‘的无效使用”。

如果B结构在这里是不完整的,那么为什么它在代码片段2中不不完整呢?

使用的编译器标志:-std=c++17 -O3 -Wall -Werror。提前谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-16 10:53:40

我认为这些本质上归结为[temp.inst]/2 (强调我的):

类模板专门化的隐式实例化导致声明的隐式实例化,但不包括类成员函数、成员类、作用域成员枚举、静态数据成员、成员模板和朋友的定义()、默认参数或no以外说明符;…。

[temp.inst]/9

实现不应隐式实例化…。类模板…的静态数据成员除非需要这样的实例化。

标准中关于隐式模板实例化的措辞为解释留下了许多细节。通常,在我看来,除非规范明确地这样说,否则您根本不能依赖模板的部分不被实例化。因此:

片段#1

问:为什么这段代码要编译?从B继承时,我们不是在实例化A吗?B中没有VD,所以编译器不应该在这里抛出一个错误吗?

您正在实例化A<B>。但是实例化A<B>只实例化声明,而不是其静态数据成员的定义。VB的使用方式从来不需要定义才能存在。编译器应该接受这段代码。

片段#2

问:为什么它要用gcc9 9编译/为什么不用clang9编译?

正如Jarod42所指出的,AB的声明包含一个占位符类型。在我看来,标准的措辞似乎并不十分清楚在这里应该发生什么。包含占位符类型触发器占位符类型演绎的静态数据成员声明的实例化是否构成了需要定义静态数据成员的用法?我在标准中找不到明确对此说“是”或“不是”的措辞。因此,我要说,这两种解释在这里同样有效,因此,GCC和clang都是正确的…。

片段#3

如果B结构在这里是不完整的,那么为什么它在代码片段2中不不完整呢?

类类型只有在到达类说明符}的关闭[class.mem]/6时才能完成。因此,在所有代码段中隐式实例化B期间,A<B>是不完整的。只是这与代码片段#1无关,在代码片段#2中,clang给出了一个错误No member named AD in B。类似于代码片段#2的情况,我无法找到确切的成员别名声明何时被实例化的措辞。但是,与静态数据成员的定义不同,在类模板的隐式实例化过程中,没有明确防止成员别名声明实例化的措辞。因此,我认为GCC和clang的行为都是对…标准的有效解释。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59353546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档