编译器什么时候需要计算别名?

When does the compiler need to compute an alias?

考虑以下代码:

template <class T>
struct computation {
    using type = /* something based on T that takes time to compile */;
};

现在考虑两个代码:

using x = computation<T>;

和:

using y = typename computation<T>::type;

我想知道该标准是否暗示:

换句话说,我想知道该标准是否指定了最有可能转化为“合理”编译器实现表的选项 A 或选项 B 的任何内容。我知道该标准对编译器实现没有任何说明,但是例如,如果它要求 ::type 在被专门调用之前不必存在,那将有利于选项 A.

注意: 根据我的经验,我很确定 g++clang++msvcintel遵循选项 A),但我不知道这是否只是纯粹的运气,因为它与标准中的某些内容有关。

我假设 T 是一个实际的 non-dependent 类型,而不是另一个模板参数。


using x = computation<T>;

不会导致 computation<T> 的隐式实例化。因此,此时编译器没有理由尝试计算 type,特别是因为需要忽略任何实例化失败。如果 type 的计算会产生无效类型或否则会失败,程序可能不会编译失败。

using y = computation<T>::type;

确实需要 computation<T> 的隐式实例化,因为范围解析运算符应用于它。隐式实例化包括计算 computation<T> 内的类型别名。编译器 必须 执行计算,因为如果计算失败或产生无效类型,则程序将 ill-formed 并且编译器需要对其进行诊断。

这实际上并不具体依赖于 ::type 部分。即使它是另一个类型别名的 ::type2,class 模板特化的隐式实例化也需要计算 type.

类似地,在任何其他需要它完整的上下文中使用 computation<T> 将需要隐式实例化,因此需要计算 type,例如

auto z = computation<T>{};